////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//   Wireless Communication Library 7                                         //
//                                                                            //
//   Copyright (C) 2006-2024 Mike Petrichenko                                 //
//                           Soft Service Company                             //
//                           All Rights Reserved                              //
//                                                                            //
//   http://www.btframework.com                                               //
//                                                                            //
//   support@btframework.com                                                  //
//   shop@btframework.com                                                     //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <vector>
#include <set>

#include <tchar.h>

#include "..\Common\wclHelpers.h"
#include "..\Common\wclMessaging.h"
#include "..\Communication\wclConnections.h"

#include "wclBluetoothErrors.h"

using namespace wclCommon;
using namespace wclCommunication;

namespace wclBluetooth
{

/* Some useful constants. */

/// <summary> Wii Remote HID report length. </summary>
#define WCL_WII_REMOTE_REPORT_LENGTH			22

/// <summary> The minimum allowed scan interval value (2.5ms) </summary>
#define WCL_BLE_MIN_SCAN_INTERVAL				4
/// <summary> The maximum allowed scan interval value (10.24s) </summary>
#define WCL_BLE_MAX_SCAN_INTERVAL				16384
/// <summary> Default BLE scan interval value (118.125ms). </summary>
#define WCL_BLE_DEFAULT_SCAN_INTERVAL			189

/// <summary> The minimum allowed scan window value (2.5ms) </summary>
#define WCL_BLE_MIN_SCAN_WINDOW					4
/// <summary> The maximum allowed scan window value (10.24s) </summary>
#define WCL_BLE_MAX_SCAN_WINDOW					16384
/// <summary> Default BLE scan window value (18.125ms). </summary>
#define WCL_BLE_DEFAULT_SCAN_WINDOW				29

/// <summary> The minimum allowed advertising interval (20ms) </summary>
#define WCL_BLE_MIN_ADVERTISING_INTERVAL		32
/// <summary> The maximum allowed advertising interval (10.24s) </summary>
#define WCL_BLE_MAX_ADVERTISING_INTERVAL		16384
/// <summary> Default BLE advertising interval (100ms). </summary>
#define WCL_BLE_DEFAULT_ADVERTISING_INTERVAL	160

/* Forward declaration */

class CwclBluetoothRadio;
class CwclBluetoothManager;
class CwclRfCommServerClientConnection;
class CwclGattLocalCharacteristic;
class CwclGattLocalCharacteristicReadRequest;
class CwclGattLocalCharacteristicWriteRequest;
class CwclGattLocalService;
class CwclGattServerConnection;
class CwclGattServerClient;

/* Data types */

/// <summary> Supported Bluetooth APIs (drivers). </summary>
typedef enum
{
	/// <summary> BlueSoleil Bluetooth driver. </summary>
	baBlueSoleil,
	/// <summary> Microsoft Bluetooth driver. </summary>
	baMicrosoft,
	/// <summary> Toshiba Bluetooth driver. </summary>
	baToshiba,
	/// <summary> Silicon Labs BLED112 module. </summary>
	baBled112
} wclBluetoothApi;
/// <summary> The set of APIs that should be used by Bluetooth
///   Framework. </summary>
/// <seealso cref="wclBluetoothApi" />
typedef std::set<wclBluetoothApi> wclBluetoothApis;

/// <summary> A remote device types. </summary>
typedef enum
{
	/// <summary> Classic Bluetooth device. </summary>
	dtClassic,
	/// <summary> BLE (Bluetooth Low Energy) device. </summary>
	dtBle,
	/// <summary> Mixed device (supports both classic and LE
	///   functions). </summary>
	dtMixed,
	/// <summary> Unknown device type. </summary>
	dtUnknown
} wclBluetoothDeviceType;

/// <summary> The structure represents a Bluetooth Service record. </summary>
typedef struct
{
	/// <summary> The service' handle. </summary>
	unsigned long Handle;
	/// <summary> The service's UUID. </summary>
	GUID Uuid;
	/// <summary> The service's RFCOMM channel number. For non-RFCOMM
	///   services this value is <c>0</c>. </summary>
	unsigned char Channel;
	/// <summary> The service's name. </summary>
	tstring Name;
	/// <summary> The service's comment. </summary>
	tstring Comment;
} wclBluetoothService;
/// <summary> The dynamic array for the service's list. </summary>
/// <seealso cref="wclBluetoothService" />
typedef std::vector<wclBluetoothService> wclBluetoothServices;

/// <summary> Bluetooth MAC address array. </summary>
typedef std::vector<__int64> wclBluetoothAddresses;
/// <summary> The Bluetooth installed services GUIDs array. </summary>
typedef std::vector<GUID> wclBluetoothInstalledServices;

/// <summary> The record describes created virtual COM port. </summary>
typedef struct
{
	/// <summary> Remote device MAC address. </summary>
	__int64 Address;
	/// <summary> Service's UUID. </summary>
	GUID Service;
	/// <summary> Virtual COM port number. </summary>
	unsigned short Number;
	/// <summary> Indicates outgoing vCOM. </summary>
	/// <remarks> If this member is <c>True</c> the vCOM is outgoing. If this
	///   member is <c>False</c> the vCOM is incoming. </remarks>
	bool Outgoing;
} wclVirtualComPort;
/// <summary> Virtual COM ports array. </summary>
/// <seealso cref="wclVirtualComPort" />
typedef std::vector<wclVirtualComPort> wclVirtualComPorts;

/// <summary> The <c>wclBluetoothDiscoverKind</c> enumeration describes
///   Bluetooth devices discovering methods. </summary>
typedef enum
{
	/// <summary> Discover only Classic Bluetooth devices. </summary>
	dkClassic,
	/// <summary> Discovers only Bluetooth Low Energy devices. </summary>
	dkBle
} wclBluetoothDiscoverKind;

/// <summary> The type describes the array of the additional protocols list
///   for a server service record. </summary>
typedef std::vector<unsigned short> wclBluetoothSdpProtocols;

/// <summary> The structure describes the Bluetooth Profile for the server
///   service record. </summary>
typedef struct
{
	/// <summary> The 16 buts profile's UUID. </summary>
	unsigned short Uuid;
	/// <summary> The profile's version number. </summary>
	unsigned short Version;
} wclBluetoothSdpProfile;
/// <summary> The type describes the array of the additional profiles
///   list for a server service record. </summary>
/// <seealso cref="wclBluetoothSdpProfile" />
typedef std::vector<wclBluetoothSdpProfile> wclBluetoothSdpProfiles;

/// <summary> The type describes the byte stream that used for adding
///   additional supported formats for a server service record. </summary>
typedef std::vector<unsigned char> wclBluetoothSdpFormats;

/// <summary> The structure contains information about a Bluetooth Low
///   Energy (LE) Universally Unique Identifier (UUID). </summary>
typedef struct
{
    /// <summary> Indicates if the Low Energy (LE) UUID a 16-bit shortened
    ///   value, or if it is the long 128-bit value. </summary>
    bool IsShortUuid;
    /// <summary> The short 16-bit value of the UUID. This member applies only
    ///   if <c>IsShortUuid</c> is <c>True</c>. </summary>
    unsigned short ShortUuid;
    /// <summary> The long 128-bit value of the UUID. This member applies only
    ///   if <c>IsShortUuid</c> is <c>False</c>. </summary>
    GUID LongUuid;
} wclGattUuid;

/// <summary> The structure describes a Bluetooth Low Energy (LE) generic
///   attribute (GATT) profile service. </summary>
typedef struct
{
    /// <summary> The Universally Unique ID (UUID) of the Bluetooth LE GATT
    ///   profile service. </summary>
    /// <seealso cref="wclGattUuid" />
    wclGattUuid Uuid;
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   attributes. </summary>
    unsigned short Handle;
} wclGattService;
/// <summary> The list of GATT services. </summary>
/// <seealso cref="wclGattService" />
typedef std::vector<wclGattService> wclGattServices;

/// <summary> The structure describes a Bluetooth Low Energy (LE) generic
///   attribute (GATT) profile characteristic. </summary>
typedef struct
{
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   service. </summary>
    unsigned short ServiceHandle;
    /// <summary> The Universally Unique ID (UUID) of the
    ///   characteristic. </summary>
    /// <seealso cref="wclGattUuid" />
    wclGattUuid Uuid;
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   attributes. </summary>
    unsigned short Handle;
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   characteristic value. </summary>
    unsigned short ValueHandle;
    /// <summary> The characteristic can be broadcast. </summary>
    bool IsBroadcastable;
    /// <summary> The characteristic can be read. </summary>
    bool IsReadable;
    /// <summary> The characteristic can be written to. </summary>
    bool IsWritable;
    /// <summary> The characteristic can be written to without requiring
    ///   a response. </summary>
    bool IsWritableWithoutResponse;
    /// <summary> The characteristic can be signed writable. </summary>
    bool IsSignedWritable;
    /// <summary> The characteristic can be updated by the device through
    ///   Handle Value Notifications, and the new value will be returned
    ///   through the event. </summary>
    bool IsNotifiable;
    /// <summary> The characteristic can be updated by the device through
    ///   Handle Value Indications, and the new value will be returned through
    ///   the event. </summary>
    bool IsIndicatable;
    /// <summary> The characteristic has extended properties, which will be
    ///   presented through a Characteristic Extended Properties
    ///   descriptor. </summary>
    bool HasExtendedProperties;
} wclGattCharacteristic;
/// <summary> The list of GATT characteristics. </summary>
/// <seealso cref="wclGattCharacteristic" />
typedef std::vector<wclGattCharacteristic> wclGattCharacteristics;

/// <summary> The enumeration describes the different types of Bluetooth LE
///   generic attributes (GATT). </summary>
typedef enum
{
    /// <summary> The characteristic value has additional properties that
    ///   describe how it can be used, or how it can be accessed. </summary>
    dtCharacteristicExtendedProperties,
    /// <summary> The characteristic value contains a string that is a user
    ///   textual description. </summary>
    dtCharacteristicUserDescription,
    /// <summary> The characteristic value may be configured by the
    ///   client. </summary>
    dtClientCharacteristicConfiguration,
    /// <summary> The characteristic value may be configured for the
    ///   server. </summary>
    dtServerCharacteristicConfiguration,
    /// <summary> The format of the characteristic value. </summary>
    dtCharacteristicFormat,
    /// <summary> The format of an aggregated characteristic value. </summary>
    dtCharacteristicAggregateFormat,
    /// <summary> The characteristic value is customized. </summary>
    dtCustomDescriptor
} wclGattDescriptorType;

/// <summary> The structure describes a Bluetooth Low Energy (LE) generic
///   attribute (GATT) profile descriptor. </summary>
typedef struct
{
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   service. </summary>
    unsigned short ServiceHandle;
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   characteristic. </summary>
    unsigned short CharacteristicHandle;
    /// <summary> The type of the Bluetooth LE GATT descriptor. </summary>
    /// <seealso cref="wclGattDescriptorType" />
    wclGattDescriptorType DescriptorType;
    /// <summary> The Universally Unique ID (UUID) of the Bluetooth LE GATT
    ///   descriptor. </summary>
    /// <seealso cref="wclGattUuid" />
    wclGattUuid Uuid;
    /// <summary> The handle to the Bluetooth LE GATT profile
    ///   attributes. </summary>
    unsigned short Handle;
} wclGattDescriptor;
/// <summary> The list of GATT descriptors. </summary>
/// <seealso cref="wclGattDescriptor" />
typedef std::vector<wclGattDescriptor> wclGattDescriptors;

/// <summary> The structure contains of the different characteristic
///   extended property members. </summary>
typedef struct
{
    /// <summary> The parent characteristic value is reliable write
    ///   enabled. </summary>
    bool IsReliableWriteEnabled;
    /// <summary> The characteristic user description descriptor
    ///   is writable. </summary>
    bool IsAuxiliariesWritable;
} wclGattCharacteristicExtendedProperties;

/// <summary> The structure describes the different client characteristic
///   configuration members. </summary>
typedef struct
{
    /// <summary> Whether the characteristic has been registered with the device
    ///   to receive Handle Value Notifications. <c>True</c> if the
    ///   characteristic has been registered. Otherwise,
    ///   <c>False</c>. </summary>
    bool IsSubscribeToNotification;
    /// <summary> Whether the characteristic has been registered with the device
    ///   to receive Handle Value Indications. <c>true</c> if the characteristic
    ///   has been registered. Otherwise, <c>False</c>. </summary>
    bool IsSubscribeToIndication;
} wclGattClientCharacteristicConfiguration;

/// <summary> The structure describes the different server characteristic
///   configuration members. </summary>
typedef struct
{
    /// <summary> The parent characteristic value can be broadcast. </summary>
    bool IsBroadcast;
} wclGattServerCharacteristicConfiguration;

/// <summary> The characteristic presentation formats. </summary>
typedef enum
{
	/// <summary> Reserved for future use. </summary>
	fmtRfu = 0x00,
	/// <summary> Boolean. </summary>
	fmtBoolean = 0x01,
	/// <summary> Unsigned 2-bit integer. </summary>
	fmt2Bit = 0x02,
	/// <summary> Unsigned 4-bit integer. </summary>
	fmtNibble = 0x03,
	/// <summary> Unsigned 8-bit integer. </summary>
	fmtUInt8 = 0x04,
	/// <summary> Unsigned 12-bit integer. </summary>
	fmtUInt12 = 0x05,
	/// <summary> Unsigned 16-bit integer. </summary>
	fmtUInt16 = 0x06,
	/// <summary> Unsigned 24-bit integer. </summary>
	fmtUInt24 = 0x07,
	/// <summary> Unsigned 32-bit integer. </summary>
	fmtUInt32 = 0x08,
	/// <summary> Unsigned 48-bit integer. </summary>
	fmtUInt48 = 0x09,
	/// <summary> Unsigned 64-bit integer. </summary>
	fmtUInt64 = 0x0A,
	/// <summary> Unsigned 128-bit integer. </summary>
	fmtUInt128 = 0x0B,
	/// <summary> Signed 8-bit integer. </summary>
	fmtSInt8 = 0x0C,
	/// <summary> Signed 12-bit integer. </summary>
	fmtSInt12 = 0x0D,
	/// <summary> Signed 16-bit integer. </summary>
	fmtSInt16 = 0x0E,
	/// <summary> Signed 24-bit integer. </summary>
	fmtSInt24 = 0x0F,
	/// <summary> Signed 32-bit integer. </summary>
	fmtSInt32 = 0x10,
	/// <summary> Signed 48-bit integer. </summary>
	fmtSInt48 = 0x11,
	/// <summary> Signed 64-bit integer. </summary>
	fmtSInt64 = 0x12,
	/// <summary> Signed 128-bit integer. </summary>
	fmtSInt128 = 0x13,
	/// <summary> IEEE-754 32-bit floating point. </summary>
	fmtFloat32 = 0x14,
	/// <summary> IEEE-754 64-bit floating point. </summary>
	fmtFloat64 = 0x15,
	/// <summary> IEEE-11073 16-bit SFLOAT. </summary>
	fmtSFloat = 0x16,
	/// <summary> IEEE-11073 32-bit FLOAT. </summary>
	fmtFloat = 0x17,
	/// <summary> IEEE-20601 format. </summary>
	fmtDUint16 = 0x18,
	/// <summary> UTF-8 string. </summary>
	fmtUtf8S = 0x19,
	/// <summary> UTF-16 string. </summary>
	fmtUtf16S = 0x1A,
	/// <summary> Opaque Structure. </summary>
	fmtStruct = 0x1B
} wclGattPresentationFormat;

/// <summary> The structure describes the different characteristic format
///   members. </summary>
typedef struct
{
    /// <summary> The format of the parent characteristic value. </summary>
    /// <seealso cref="wclGattPresentationFormat" />
	wclGattPresentationFormat Format;
    /// <summary> The exponent value to use to determine how the value of the
    ///   characteristic value is further formatted. </summary>
    unsigned char Exponent;
    /// <summary> The unit of the characteristic value as defined in the
    ///   Assigned Numbers specification. </summary>
    unsigned short AUnit;
    /// <summary> The name-space where the unit is defined in the Assigned
    ///   Numbers specification. </summary>
    unsigned char NameSpace;
    /// <summary> The Universally Unique ID (UUID) that describes the format of
    ///   the parent characteristic value. </summary>
    unsigned short Description;
} wclGattCharacteristicFormat;
/// <summary> The <see cref="wclGattCharacteristicFormat" /> array. </summary>
/// <seealso cref="wclGattCharacteristicFormat" />
typedef std::vector<wclGattCharacteristicFormat> wclGattCharacteristicFormats;

/// <summary> The structure contains a GATT characteristic user description
///   descriptor data. </summary>
typedef struct
{
	/// <summary> The characteristic's user description. </summary>
	tstring Description;
} wclGattCharactertisticUserDescription;

/// <summary> The structure contains a GATT characteristic aggregate format
///   data. </summary>
typedef struct
{
	/// <summary> The GATT characteristic presentation format descriptor
	///   handles array. </summary>
	std::vector<unsigned short> Handles;
} wclGattCharacteristicAggregateFormat;

/// <summary> The structure contains a descriptor value. </summary>
typedef struct
{
    /// <summary> The type of the descriptor value. </summary>
    /// <seealso cref="wclGattDescriptorType" />
    wclGattDescriptorType AType;
    /// <summary> The Universally Unique ID (UUID) of the descriptor
    ///   value. </summary>
    /// <seealso cref="wclGattUuid"/>
    wclGattUuid Uuid;
    /// <summary> Container structure for the different characteristic
    ///   extended property members. This member is valid only if <c>AType</c>
    ///   is <c>dtCharacteristicExtendedProperties</c></summary>
    /// <seealso cref="wclGattCharacteristicExtendedProperties" />
    wclGattCharacteristicExtendedProperties CharacteristicExtendedProperties;
    /// <summary> Container structure for the different client characteristic
    ///   configuration members. This member is valid only if <c>AType</c> is
    ///   <c>dtClientCharacteristicConfiguration</c>. </summary>
    /// <seealso cref="wclGattClientCharacteristicConfiguration" />
    wclGattClientCharacteristicConfiguration ClientCharacteristicConfiguration;
    /// <summary> Container structure for the different server characteristic
    ///   configuration members. This member is valid only if <c>AType</c> is
    ///   <c>dtServerCharacteristicConfiguration</c>. </summary>
    /// <seealso cref="wclGattServerCharacteristicConfiguration" />
    wclGattServerCharacteristicConfiguration ServerCharacteristicConfiguration;
    /// <summary> Container structure for the different characteristic format
    ///   members. This member is valid only if <c>AType</c> is
    ///   <c>dtCharacteristicFormat</c>. </summary>
    /// <seealso cref="wclGattCharacteristicFormat" />
    wclGattCharacteristicFormat CharacteristicFormat;
	/// <summary> Contains data structure of a characteristic's aggregate
	///   format descriptor. This member is valid only if <c>AType</c> is
	///   <c>dtCharacteristicAggregateFormat</c> </summary>
	/// <seealso cref="wclGattCharacteristicAggregateFormat" />
	wclGattCharacteristicAggregateFormat CharacteristicAggregateFormat;
	/// <summary> Container structure for the characteristic's user description
	///   descriptor data. This member is valid only if <c>AType</c> is
	///   <c>dtCharacteristicUserDescription</c>. </summary>
	/// <seealso cref="wclGattCharactertisticUserDescription" />
	wclGattCharactertisticUserDescription UserDescription;
    /// <summary> The descriptor value data. An application is
    ///   responsible to free a memory allocated for this dynamic array.
    ///   If there is no data the member is <c>NULL</c>. </summary>
	unsigned char* Data;
	/// <summary> The descriptor value length in bytes. </summary>
	unsigned long Length;
} wclGattDescriptorValue;

/// <summary> This enumeration describes how a GATT reading operation
///   should be executed. </summary>
typedef enum
{
    /// <summary> Use default behavior. </summary>
    goNone,
    /// <summary> The value is to be read directly from the device. This
    ///   overwrites the one in the cache if one is already
    ///   present. </summary>
    goReadFromDevice,
    /// <summary> The value is to be read from the cache (regardless of whether
    ///   it is present in the cache or not). </summary>
    goReadFromCache
} wclGattOperationFlag;

/// <summary> Represents the desired security level for GATT communication. </summary>
typedef enum
{
	/// <summary> Uses the default protection level. </summary>
	plNone,
	/// <summary> Require the link to be authenticated. </summary>
	plAuthentication,
	/// <summary> Require the link to be encrypted. </summary>
	plEncryption,
	/// <summary> Require the link to be encrypted and authenticated. </summary>
	plEncryptionAndAuthentication
} wclGattProtectionLevel;

/// <summary> The GATT write operation mode. </summary>
typedef enum
{
	/// <summary> Execute write operation as Write With Response. </summary>
	wkWithResponse,
	/// <summary> Execute write operation as Write Without Response if a
	///   characteristic supports such method. If a characteristic does not
	///   support Write Without Response the
	///   <see cref="WCL_E_BLUETOOTH_LE_WRITE_WITHOUT_RESPONSE_NOT_SUPPORTED" />
	///   error returned. </summary>
	wkWithoutResponse,
	/// <summary> Automatic detection of write operation mode. If a
	///   characteristic supports Write Without Response then this method will
	///   be used. Otherwise the Write With Response operation
	///   executes. The default write operation mode. </summary>
	wkAuto
} wclGattWriteKind;

/// <summary> The GATT subscription method. </summary>
typedef enum
{
	/// <summary> Subscribe to notifications. </summary>
	skNotification,
	/// <summary> Subscribe to indication. </summary>
	skIndication,
	/// <summary> A subscription method is controlled by a characteristic
	///   properties. </summary>
	skManual
} wclGattSubscribeKind;

/// <summary> The enumeration represents the GATT local characteristic
///   properties, as defined by the GATT profile. </summary>
typedef enum
{
	/// <summary> The characteristic supports signed writes. </summary>
	cpAuthenticatedSignedWritable,
	/// <summary> The characteristic supports broadcasting. </summary>
	cpBroadcastable,
	/// <summary> The ExtendedProperties Descriptor is present. </summary>
	cpExtendedProperties,
	/// <summary> The characteristic is indicatable. </summary>
	cpIndicatable,
	/// <summary> The characteristic is notifiable. </summary>
	cpNotifiable,
	/// <summary> The characteristic is readable. </summary>
	cpReadable,
	/// <summary> The characteristic supports reliable writes. </summary>
	cpReliableWritable,
	/// <summary> The characteristic has writable auxiliaries. </summary>
	cpWritableAuxiliaries,
	/// <summary> The characteristic is writable. </summary>
	cpWritable,
	/// <summary> The characteristic supports Write Without Response. </summary>
	cpWritableWithoutResponse
} wclGattLocalCharacteristicProperty;
/// <summary> The set of GATT local characteristic properties, as defined by
///   the GATT profile. </summary>
/// <seealso cref="wclGattLocalCharacteristicProperty" />
typedef std::set<wclGattLocalCharacteristicProperty> wclGattLocalCharacteristicProperties;

/// <summary> The structure describes the local GATT descriptor. </summary>
typedef struct
{
	/// <summary> The descriptor's UUID. </summary>
	unsigned short			Uuid;
	/// <summary> The read protection level of the descriptor. </summary>
	/// <seealso cref="wclGattProtectionLevel" />
	wclGattProtectionLevel	ReadProtectionLevel;
	/// <summary> The write protection level of the descriptor. </summary>
	/// <seealso cref="wclGattProtectionLevel" />
	wclGattProtectionLevel	WriteProtectionLevel;
	/// <summary> The descriptor's data. </summary>
	unsigned char*			Data;
	/// <summary> The descriptor's data size. </summary>
	unsigned char			Size;
} wclGattLocalDescriptor;
/// <summary> GATT local descriptors array. </summary>
/// <seealso cref="wclGattLocalDescriptor" />
typedef std::vector<wclGattLocalDescriptor> wclGattLocalDescriptors;

/// <summary> The structure represents a GATT local characteristic
///   parameters. </summary>
typedef struct
{
	/// <summary> Custom descriptors. </summary>
	/// <remarks> This array must not include Presentation Format, Aggregate
	///   Format, Client Configuration, Server Configuration and User
	///   Description descriptors. </remarks>
	/// <seealso cref="wclGattLocalDescriptors" />
	wclGattLocalDescriptors Descriptors;
	/// <summary> The characteristic's presentation formats. </summary>
	/// <remarks> If this field is set the Characteristic Presentation Format
    ///   descriptor (one ore more) will be added. </remarks>
    /// <seealso cref="TwclGattCharacteristicFormat" />
	wclGattCharacteristicFormats PresentationFormats;
	/// <summary> The characteristic's properties. </summary>
	/// <seealso cref="wclGattLocalCharacteristicProperties" />
	wclGattLocalCharacteristicProperties Props;
	/// <summary> The read protection level of a local
	///   characteristic. </summary>
	/// <seealso cref="wclGattProtectionLevel" />
	wclGattProtectionLevel ReadProtectionLevel;
	/// <summary> The characteristic's user-friendly description. </summary>
	/// <remarks> If this property is set the Characteristic User Description
    ///   descriptor will be added. </remarks>
	tstring UserDescription;
	/// <summary> The write protection level of a local
	///   characteristic. </summary>
	/// <seealso cref="wclGattProtectionLevel" />
	wclGattProtectionLevel WriteProtectionLevel;
} wclGattLocalCharacteristicParameters;

/// <summary> Specifies the Bluetooth LE scanning mode. </summary>
typedef enum
{
	/// <summary> Scanning mode is active. This indicates that scan request
	///   packets will be sent from the platform to actively query for more
	///   advertisement data of type ScanResponse. </summary>
	smActive,
	/// <summary> Scanning mode is passive. </summary>
	smPassive
} wclBluetoothLeScanningMode;

/// <summary> The bytes array of the Bluetooth LE advertisement frame raw data. </summary>
typedef std::vector<unsigned char> wclBluetoothLeAdvertisementFrameRawData;

/// <summary> Types of the Bluetooth LE advertisement packet. </summary>
typedef enum
{
	/// <summary> <para> The advertisement is undirected and indicates that the
	///   device is connectable and scannable. This advertisement type can carry
	///   data. </para>
	///   <para> This corresponds with the <c>ADV_IND</c> type defined in the
	///   Bluetooth LE specifications. </para> </summary>
	atConnectableUndirected,
	/// <summary> <para> The advertisement is directed and indicates that the
	///   device is connectable but not scannable. This advertisement type
	///   cannot carry data. </para>
	///   <para> This corresponds with the <c>ADV_DIRECT_IND</c> type defined in
	///   the Bluetooth LE specifications. </para> </summary>
	atConnectableDirected,
	/// <summary> <para> The advertisement is undirected and indicates that the
	///   device is scannable but not connectable. This advertisement type can
	///   carry data. </para>
	///   <para> This corresponds with the <c>ADV_SCAN_IND</c> type defined in
	///   the Bluetooth LE specifications. </para> </summary>
	atScannableUndirected,
	/// <summary> <para> The advertisement is undirected and indicates that the
	///   device is not connectable nor scannable. This advertisement type can
	///   carry data. </para>
	///   <para> This corresponds with the <c>ADV_NONCONN_IND</c> type defined
	///   in the Bluetooth LE specifications. </para> </summary>
	atNonConnectableUndirected,
	/// <summary> <para> This advertisement is a scan response to a scan request
	///   issued for a scannable advertisement. This advertisement type can
	///   carry data. </para>
	///   <para> This corresponds with the <c>SCAN_RSP</c> type defined in the
	///   Bluetooth LE specifications. </para> </summary>
	atScanResponse,
	/// <summary> This advertisement is a 5.0 extended advertisement. This
	///   advertisement type may have different properties, and is not
	///   necessarily directed, connected, scannable, nor a scan
	///   response. </summary>
	atExtended,
	/// <summary> Unknown advertisement packet type. </summary>
    atUnknown
} wclBluetoothLeAdvertisementType;

/// <summary> Flags used to match flags contained inside a Bluetooth LE
///   advertisement payload. </summary>
typedef enum
{
	/// <summary> Bluetooth LE Limited Discoverable Mode. </summary>
	afLimitedDiscoverableMode,
	/// <summary> Bluetooth LE General Discoverable Mode. </summary>
	afGeneralDiscoverableMode,
	/// <summary> Bluetooth BR/EDR not supported. </summary>
	afClassicNotSupported,
	/// <summary> Simultaneous Bluetooth LE and BR/EDR to same device
	///   capable (controller). </summary>
	afDualModeControllerCapable,
	/// <summary> Simultaneous Bluetooth LE and BR/EDR to same device capable
	///   (host). </summary>
	afDualModeHostCapable
} wclBluetoothLeAdvertisementFlag;
/// <summary> Set of the
///   <see cref="wclBluetooth::wclBluetoothLeAdvertisementFlag" />. </summary>
/// <seealso cref="wclBluetooth::wclBluetoothLeAdvertisementFlag" />
typedef std::set<wclBluetoothLeAdvertisementFlag> wclBluetoothLeAdvertisementFlags;

/// <summary> Extended advertisement frame flags. </summary>
typedef enum
{
	/// <summary> Indicates whether a Bluetooth Address was omitted from the
	///   received advertisement. </summary>
	efAnonymous,
	/// <summary> Indicates whether the received advertisement is
	///   connectable. </summary>
	efConnectable,
	/// <summary> Indicates whether the received advertisement is
	///   directed. </summary>
	efDirected,
	/// <summary> Indicates whether the received advertisement is
	///   scannable. </summary>
	efScannable,
	/// <summary> Indicates whether the received advertisement is a scan
	///   response. </summary>
	efScanResponse
} wclBluetoothLeExtendedFrameFlag;
/// <summary> Set of the
///   <see cref="TwclBluetoothLeExtendedFrameFlag" />. </summary>
/// <seealso cref="TwclBluetoothLeExtendedFrameFlag" />
typedef std::set<wclBluetoothLeExtendedFrameFlag> wclBluetoothLeExtendedFrameFlags;

/// <summary> The array of Eddystone encoded URL bytes. </summary>
/// <remarks> For internal use only. </remarks>
typedef std::vector<unsigned char> wclEddystoneEncodedUrl;

/// <summary> The enumeration specifies the "Man in the Middle" protection
///   required for authentication. </summary>
typedef enum
{
	/// <summary> Protection against a "Man in the Middle" attack is not
	///   required for authentication. </summary>
	mitmProtectionNotRequired,
	/// <summary> Protection against a "Man in the Middle" attack is required
	///   for authentication. </summary>
	mitmProtectionRequired,
	/// <summary> Protection against a "Man in the Middle" attack is not
	///   required for bonding. </summary>
	mitmProtectionNotRequiredBonding,
	/// <summary> Protection against a "Man in the Middle" attack is required
	///   for bonding. </summary>
	mitmProtectionRequiredBonding,
	/// <summary> Protection against a "Man in the Middle" attack is not
	///   required for General Bonding. </summary>
	mitmProtectionNotRequiredGeneralBonding,
	/// <summary> Protection against a "Man in the Middle" attack is required
	///   for General Bonding. </summary>
	mitmProtectionRequiredGeneralBonding,
	/// <summary> Protection against "Man in the Middle" attack is not
	///   defined. </summary>
	mitmProtectionNotDefined
} wclBluetoothMitmProtection;

/// <summary> The Bluetooth LE pairing protection levels. </summary>
typedef enum
{
	/// <summary> Use default protection level. </summary>
	pplDefault,
	/// <summary> Pair the device using no levels of protection. (Mode 1,
	///   Level 1). </summary>
	pplNone,
	/// <summary> Pair the device using encryption. (Mode 1,
	///   Level 2). </summary>
	pplEncryption,
	/// <summary> Pair the device using encryption and authentication. (Mode 1,
	///   Level 3). </summary>
	pplEncryptionAndAuthentication
} wclBluetoothLeProtectionLevel;

/// <summary> The enumeration defines the input/output capabilities of a
///   Bluetooth Device. </summary>
typedef enum
{
	/// <summary> The Bluetooth device is capable of output via display
	///   only. </summary>
	iocapDisplayOnly,
	/// <summary> The Bluetooth device is capable of output via a display, and
	///   has the additional capability to presenting a yes/no question to the
	///   user. </summary>
	iocapDisplayYesNo,
	/// <summary> The Bluetooth device is capable of input via
	///   keyboard. </summary>
	iocapKeyboardOnly,
	/// <summary> The Bluetooth device is not capable of
	///   input/output. </summary>
	iocapNoInputNoOutput,
	/// <summary> The Bluetooth device is capable of input via
	///   keyboard and of output via display. </summary>
	iocapDisplayKeyboard,
	/// <summary> The input/output capabilities for the Bluetooth device are
	///   undefined. </summary>
	iocapNotDefined
} wclBluetoothIoCapability;

/// <summary> The structure contains data used to authenticate prior to
///   establishing an Out-of-Band device pairing. </summary>
typedef struct
{
	/// <summary> A 128-bit cryptographic key used for two-way
	///   authentication. </summary>
	BYTE	C[16];
	/// <summary> A randomly generated number used for one-way authentication.
	///   If this number is not provided by the device initiating the OOB
	///   session, this value is 0. </summary>
	BYTE	R[16];
} wclBluetoothOobData;

/// <summary> Describes the Bluetooth address type. </summary>
typedef enum
{
	/// <summary> Classic Bluetooth device (public static address). </summary>
	atClassic,
	/// <summary> Public address. </summary>
	atPublic,
	/// <summary> Random address. </summary>
	atRandom,
	/// <summary> Unspecified address. </summary>
	atUnspecified
} wclBluetoothAddressType;

/// <summary> The pairing methods. </summary>
/// <remarks> The pairing method allows your application to force Classic or
///   BLE pairing when needed. </remarks>
typedef enum
{
	/// <summary> Bluetooth Framework automatically selects the pairing
	///   method based on Bluetooth device type. </summary>
	pmAuto,
	/// <summary> Bluetooth Framework forces Classic pairing. </summary>
	pmClassic,
	/// <summary> Bluetooth Framework forces LE pairing. </summary>
	pmLe
} wclBluetoothPairingMethod;

/// <summary> The structure represents a single Bluetooth LE advertisement
///   data section. </summary>
/// <remarks> This structure is used internally by the Bluetooth LE
///   advertiser. </remarks>
typedef struct
{
	/// <summary> The manufacturer ID as defined in the Bluetooth SIG
	///   Assigned Numbers. </summary>
	/// <remarks> This member is valid only when the advertisement data type is
	///   <c>LE_GAP_AD_TYPE_MANUFACTURER</c>. </remarks>
	unsigned short CompanyId;
	/// <summary> The advertisement data type. </summary>
	unsigned char DataType;
	/// <summary> The advertisement data. </summary>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData Data;
} wclBluetoothLeAdvertisementFrame;
/// <summary> The array of the Bluetooth LE advertisement data
///   sections. </summary>
/// <seealso cref="wclBluetoothLeAdvertisementFrame" />
typedef std::vector<wclBluetoothLeAdvertisementFrame> wclBluetoothLeAdvertisementFrames;

/// <summary> The structure describes the current Bluetooth LE GATT connection
///   parameters. </summary>
typedef struct
{
	/// <summary> The connection interval. </summary>
	/// <remarks> The connection interval is defined as 1.25ms increments,
	///   ranging from 6 to 3200. Time(ms) = Interval * 1.25ms. </remarks>
	unsigned short Interval;
	/// <summary> The connection latency. </summary>
	/// <remarks> The connection latency is defined in connection events,
	///   ranging from 0 to 499. </remarks>
	unsigned short Latency;
	/// <summary> The connection link supervision timeout. </summary>
	/// <remarks> The connection link supervision timeout is defined in 10ms
	///   increments, ranging from 10 to 3200.
	///   Time(ms) = LinkTimeout * 10ms. </remarks>
	unsigned short LinkTimeout;
} wclBluetoothLeConnectionParameters;

/// <summary> The enumeration defines the Bluetooth LE GATT preferred
///   connection parameters. </summary>
typedef enum
{
	/// <summary> The balanced set of connection parameters, offering a balance
	///   between throughput and power usage. </summary>
	ppBalanced,
	/// <summary> The more power-efficient set of connection parameters.
	///   Optimized for power usage at the expense of throughput. Also allows
	///   for more simultaneous connections to other Bluetooth
	///   devices. </summary>
	ppPowerOptimized,
	/// <summary> The more aggressive set of connection parameters, optimized
	///   for faster throughput at the expense of power usage. Also reduces the
	///   number of simultaneous connections that can be made to other Bluetooth
	///   devices. </summary>
	ppThroughputOptimized
} wclBluetoothLeConnectionParametersType;

/// <summary> The structure represents the Bluetooth LE GATT preferred connection
///   parameters. </summary>
typedef struct
{
	/// <summary> The minimum connection interval. </summary>
	/// <remarks> The connection interval is defined as 1.25ms increments,
	///   ranging from 6 to 3200. Time(ms) = Interval * 1.25ms. </remarks>
	unsigned short MinInterval;
	/// <summary> The maximum connection interval. </summary>
	/// <remarks> The connection interval is defined as 1.25ms increments,
	///   ranging from 6 to 3200. Time(ms) = Interval * 1.25ms. </remarks>
	unsigned short MaxInterval;
	/// <summary> The connection latency. </summary>
	/// <remarks> The connection latency is defined in connection events,
	///   ranging from 0 to 499. </remarks>
	unsigned short Latency;
	/// <summary> The connection link supervision timeout. </summary>
	/// <remarks> The connection link supervision timeout is defined in 10ms
	///   increments, ranging from 10 to 3200.
	///   Time(ms) = LinkTimeout * 10ms. </remarks>
	unsigned short LinkTimeout;
} wclBluetoothLeConnectionParametersValue;

/// <summary> Represents a LE connection PHY information. </summary>
typedef struct
{
	/// <summary> Indicates whether or not the Bluetooth LE physical layer (PHY)
	///   is LE Coded. </summary>
	bool IsCoded;
	/// <summary> Indicates whether or not the Bluetooth LE physical layer (PHY)
	///   is (uncoded) LE 1M. </summary>
	bool IsUncoded1MPhy;
	/// <summary> Indicates whether or not the Bluetooth LE physical layer (PHY)
	///   is (uncoded) LE 2M. </summary>
	bool IsUncoded2MPhy;
} wclBluetoothLeConnectionPhyInfo;

/// <summary> Represents the Bluetooth LE physical layer (PHY)
///   information. </summary>
typedef struct
{
	/// <summary> The info about the Bluetooth LE physical layer (PHY) for
	///   receive. </summary>
	/// <seealso cref="wclBluetoothLeConnectionPhyInfo" />
	wclBluetoothLeConnectionPhyInfo Receive;
	/// <summary> The info about the Bluetooth LE physical layer (PHY) for
	///   transmit. </summary>
	/// <seealso cref="wclBluetoothLeConnectionPhyInfo" />
	wclBluetoothLeConnectionPhyInfo Transmit;
} wclBluetoothLeConnectionPhy;

/// <summary> The structure represents a Wii Remote accelerometer calibration
///   data. </summary>
typedef struct
{
	/// <summary> A minimum X value. </summary>
	unsigned short MinX;
	/// <summary> A minimum Y value. </summary>
	unsigned short MinY;
	/// <summary> A minimum Z value. </summary>
	unsigned short MinZ;
	/// <summary> A maximum X value. </summary>
	unsigned short MaxX;
	/// <summary> A maximum Y value. </summary>
	unsigned short MaxY;
	/// <summary> A maximum Z value. </summary>
	unsigned short MaxZ;
} wclWiiRemoteAccelCalibration;

/// <summary> The structure contains the Wii Remote LEDs states. </summary>
typedef struct
{
	/// <summary> <c>True</c> if the first LED is turned ON. </summary>
	bool Led1;
	/// <summary> <c>True</c> if the second LED is turned ON. </summary>
	bool Led2;
	/// <summary> <c>True</c> if the third LED is turned ON. </summary>
	bool Led3;
	/// <summary> <c>True</c> if the fourth LED is turned ON. </summary>
	bool Led4;
} wclWiiRemoteLeds;

/// <summary> The Wii Remote IR sensor modes. </summary>
typedef enum
{
	/// <summary> The IR sensor is turned off. </summary>
	wiiIrOff,
	/// <summary> The basic mode. </summary>
	wiiIrBasicMode,
	/// <summary> The extended mode. </summary>
	wiiIrExtendedMode,
	/// <summary> The full mode. </summary>
	wiiIrFullMode
} wclWiiRemoteIrMode;

/// <summary> The Wii Remote IR sensor sensitivity. </summary>
typedef enum
{
	/// <summary> The IR sensor is turned off. </summary>
	wiiIrLevelOff,
	/// <summary> The Level 1. </summary>
	wiiIrLevel1,
	/// <summary> The Level 2. </summary>
	wiiIrLevel2,
	/// <summary> The Level 3. </summary>
	wiiIrLevel3,
	/// <summary> The Level 4. </summary>
	wiiIrLevel4,
	/// <summary> The Level 5. </summary>
	wiiIrLevel5,
	/// <summary> The maximum sensitivity. </summary>
	wiiIrLevelMax
} wclWiiRemoteIrSensitivity;

/// <summary> The Wii Remote extension types. </summary>
typedef enum
{
	/// <summary> No extension is connected. </summary>
	wiiNoExtension,
	/// <summary> The Nunchuk extension. </summary>
	wiiNunchuk,
	/// <summary> The Classic Controller extension. </summary>
	wiiClassicController,
	/// <summary> The Guitar extension. </summary>
	wiiGuitar,
	/// <summary> The Drums extension. </summary>
	wiiDrums,
	/// <summary> The Balance Board extension. </summary>
	wiiBalanceBoard
} wclWiiRemoteExtension;

/// <summary> The structure contains information about the Wii Remote
///   buttons. </summary>
typedef struct
{
	/// <summary> <c>True</c> if the "A" button is pressed. </summary>
	bool A;
	/// <summary> <c>True</c> if the "B" button is pressed. </summary>
	bool B;
	/// <summary> <c>True</c> if the "+" button is pressed. </summary>
	bool Plus;
	/// <summary> <c>True</c> if the "Home" button is pressed. </summary>
	bool Home;
	/// <summary> <c>True</c> if the "-" button is pressed. </summary>
	bool Minus;
	/// <summary> The "1" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool One;
	/// <summary> The "2" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Two;
	/// <summary> The "Up" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Up;
	/// <summary> The "Down" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Down;
	/// <summary> The "Left" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Left;
	/// <summary> The "Right" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Right;
} wclWiiRemoteButtons;

/// <summary> The structure represents a 3D coordinate. </summary>
typedef struct
{
	/// <summary> An X coordinate. </summary>
	unsigned short X;
	/// <summary> An Y coordinate. </summary>
	unsigned short Y;
	/// <summary> A Z coordinate. </summary>
	unsigned short Z;
} wclWiiRemote3D;

/// <summary> The structure describes a Wii Remote accelerometer
///   data. </summary>
typedef struct
{
	/// <summary> Calibration data. </summary>
	/// <seealso cref="wclWiiRemoteAccelCalibration" />
	wclWiiRemoteAccelCalibration Calibration;
	/// <summary> Values. </summary>
	/// <seealso cref="wclWiiRemote3D" />
	wclWiiRemote3D Values;
} wclWiiRemoteAccel;

/// <summary> The structure represents a 2D coordinate </summary>
typedef struct
{
	/// <summary> An X coordinate. </summary>
	unsigned short X;
	/// <summary> An Y coordinate. </summary>
	unsigned short Y;
} wclWiiRemote2D;

/// <summary> The structure contains a single IR sensor values. </summary>
typedef struct
{
	/// <summary> The IR sensor coordinates. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D Position;
	/// <summary> Indicates the size of the detected object. </summary>
	unsigned char Size;
	/// <summary> <c>True</c> is the object detected. </summary>
	bool Found;
} wclWiiRemoteIrSensor;

/// <summary> The structure contains the Wii Remote IR sensors
///   values. </summary>
typedef struct
{
	/// <summary> The IR sensor mode. </summary>
	/// <seealso cref="wclWiiRemoteIrMode" />
	wclWiiRemoteIrMode Mode;
	/// <summary> The IR sensitivity. </summary>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	wclWiiRemoteIrSensitivity Sensitivity;
	/// <summary> The array of the IR sensors. </summary>
	/// <seealso cref="wclWiiRemoteIrSensor" />
	wclWiiRemoteIrSensor Sensors[4];
} wclWiiRemoteIrSensors;

/// <summary> The structure represents a Wii Remote Nunchuk extension
///   accelerometer calibration data. </summary>
typedef struct
{
	/// <summary> The nunchuk accelerometer calibration data. </summary>
	/// <seealso cref="wclWiiRemoteAccelCalibration" />
	wclWiiRemoteAccelCalibration Accel;
	/// <summary>The joystick minimum X value. </summary>
	unsigned char MinX;
	/// <summary>The joystick center X value. </summary>
	unsigned char MidX;
	/// <summary>The joystick maximum X value. </summary>
	unsigned char MaxX;
	/// <summary>The joystick minimum Y value. </summary>
	unsigned char MinY;
	/// <summary>The joystick center Y value. </summary>
	unsigned char MidY;
	/// <summary>The joystick maximum Y value. </summary>
	unsigned char MaxY;
} wclWiiRemoteNunchukCalibration;

/// <summary> The structure describes a Wii Remote Nunchuk
///   extension. </summary>
typedef struct
{
	/// <summary> The Nunchuk extension calibration values. </summary>
	/// <seealso cref="wclWiiRemoteNunchukCalibration" />
	wclWiiRemoteNunchukCalibration Calibration;
	/// <summary> The Nunchuk extension accelerometer values. </summary>
	/// <seealso cref="wclWiiRemoteAccel" />
	wclWiiRemoteAccel Accel;
	/// <summary> The Nunchuk extension joystick calculated values. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D Joystick;
	/// <summary> The Nunchuk extension "C" button state. <c>True</c> if
	///   button is pressed. </summary>
	bool C;
	/// <summary> The Nunchuk extension "Z" button state. <c>True</c> if
	///   button is pressed. </summary>
	bool Z;
} wclWiiRemoteNunchuk;

/// <summary> The structure contains information about the Wii Remote Classic
///   Controller extension buttons. </summary>
typedef struct
{
	/// <summary> The "A" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool A;
	/// <summary> The "B" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool B;
	/// <summary> The "+" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Plus;
	/// <summary> The "Home" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Home;
	/// <summary> The "-" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Minus;
	/// <summary> The "Up" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Up;
	/// <summary> The "Down" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Down;
	/// <summary> The "Left" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Left;
	/// <summary> The "Right" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Right;
	/// <summary> The "X" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool X;
	/// <summary> The "Y" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Y;
	/// <summary> The "ZL" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool ZL;
	/// <summary> The "ZR" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool ZR;
	/// <summary> The "L" (Left Trigger) button state. <c>True</c> if the button
	///   is pressed. </summary>
	bool L;
	/// <summary> The "R" (Right Trigger) button state. <c>True</c> if the
	///   button is pressed. </summary>
	bool R;
} wclWiiRemoteClassicControllerButtons;

/// <summary> The structure represents a Wii Remote Classic Controller
///   accelerometer calibration data. </summary>
typedef struct
{
	/// <summary> The left joystick minimum X value. </summary>
	unsigned char LeftMinX;
	/// <summary> The left joystick center X value. </summary>
	unsigned char LeftMidX;
	/// <summary> The left joystick maximum X value. </summary>
	unsigned char LeftMaxX;
	/// <summary> The left joystick minimum Y value. </summary>
	unsigned char LeftMinY;
	/// <summary> The left joystick center Y value. </summary>
	unsigned char LeftMidY;
	/// <summary> The left joystick maximum Y value. </summary>
	unsigned char LeftMaxY;
	/// <summary> The right joystick minimum X value. </summary>
	unsigned char RightMinX;
	/// <summary> The right joystick center X value. </summary>
	unsigned char RightMidX;
	/// <summary> The right joystick maximum X value. </summary>
	unsigned char RightMaxX;
	/// <summary> The right joystick minimum Y value. </summary>
	unsigned char RightMinY;
	/// <summary> The right joystick center Y value. </summary>
	unsigned char RightMidY;
	/// <summary> The right joystick maximum Y value. </summary>
	unsigned char RightMaxY;
	/// <summary> The left trigger minimum value. </summary>
	unsigned char LeftTriggerMin;
	/// <summary> The left trigger maximum value. </summary>
	unsigned char LeftTriggerMax;
	/// <summary> The right trigger minimum value. </summary>
	unsigned char RightTriggerMin;
	/// <summary> The right trigger maximum value. </summary>
	unsigned char RightTriggerMax;
} wclWiiRemoteClassicControllerCalibration;

/// <summary> The structure describes a Wii Remote Classic controller
///   extension. </summary>
typedef struct
{
	/// <summary> The Wii Remote Classic controller calibration data. </summary>
	/// <seealso cref="wclWiiRemoteClassicControllerCalibration" />
	wclWiiRemoteClassicControllerCalibration Calibration;
	/// <summary> The Wii Remote Classic controller buttons states. </summary>
	/// <seealso cref="wclWiiRemoteClassicControllerButtons" />
	wclWiiRemoteClassicControllerButtons Buttons;
	/// <summary> The Wii Remote Classic controller left joystick
	///   value. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D LeftJoystick;
	/// <summary> The Wii Remote Classic controller right joystick
	///   value. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D RightJoystick;
	/// <summary> The Wii Remote Classic controller left trigger
	///   value. </summary>
	unsigned char LeftTrigger;
	/// <summary> The Wii Remote Classic controller right trigger
	///   value. </summary>
	unsigned char RightTrigger;
} wclWiiRemoteClassicController;

/// <summary> The Wii Remote Guitar extension type. </summary>
typedef enum
{
	/// <summary> The Guitar extension is the Hero 3 model. </summary>
	wiiGuitarHero3,
	/// <summary> The Guitar extension is the Hero World Tour model. </summary>
	wiiGuitarHeroWorldTour
} wclWiiRemoteGuitarType;

/// <summary> The structure contains information about the Wii Remote Guitar
///   extension buttons. </summary>
typedef struct
{
	/// <summary> The "Strum Up" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool StrumUp;
	/// <summary> The "Strum Down" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool StrumDown;
	/// <summary> The "-" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Minus;
	/// <summary> The "+" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Plus;
} wclWiiRemoteGuitarButtons;

/// <summary> The structure contains the Wii Remote Guitar extension fret
///   buttons states. </summary>
typedef struct
{
	/// <summary> The "Green" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Green;
	/// <summary> The "Red" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Red;
	/// <summary> The "Yellow" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Yellow;
	/// <summary> The "Blue" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Blue;
	/// <summary> The "Orange" button state. <c>True</c> if the button is
	///   pressed. </summary>
	bool Orange;
} wclWiiRemoteGuitarFretButtons;

/// <summary> The structure describes a Wii Remote Guitar extension
///   data. </summary>
typedef struct
{
	/// <summary> The Wii Remote Guitar extension type. </summary>
	/// <seealso cref="wclWiiRemoteGuitarType" />
	wclWiiRemoteGuitarType GuitarType;
	/// <summary> The Wii Remote Guitar extension buttons data. </summary>
	/// <seealso cref="wclWiiRemoteGuitarButtons" />
	wclWiiRemoteGuitarButtons Buttons;
	/// <summary> The Wii Remote Guitar extension fret buttons data. </summary>
	/// <seealso cref="wclWiiRemoteGuitarFretButtons" />
	wclWiiRemoteGuitarFretButtons FretButtons;
	/// <summary> The Wii Remote Guitar extension touchbar data. </summary>
	/// <seealso cref="wclWiiRemoteGuitarFretButtons" />
	wclWiiRemoteGuitarFretButtons Touchbar;
	/// <summary> The Wii Remote Guitar extension joystick data. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D Joystick;
	/// <summary> The Wii Remote Guitar extension whammy bar data. </summary>
	unsigned char WhammyBar;
} wclWiiRemoteGuitar;

/// <summary> The structure describes the Wii Remote Drums
///   extension </summary>
typedef struct
{
	/// <summary> <c>True</c> if the "Red" drum is touched. </summary>
	bool Red;
	/// <summary> <c>True</c> if the "Green" drum is touched. </summary>
	bool Green;
	/// <summary> <c>True</c> if the "Blue" drum is touched. </summary>
	bool Blue;
	/// <summary> <c>True</c> if the "Orange" drum is touched. </summary>
	bool Orange;
	/// <summary> <c>True</c> if the "Yellow" drum is touched. </summary>
	bool Yellow;
	/// <summary> <c>True</c> if the Pedal is pressed. </summary>
	bool Pedal;
	/// <summary> The "Red" drum velocity. </summary>
	unsigned char RedVelocity;
	/// <summary> The "Green" drum velocity. </summary>
	unsigned char GreenVelocity;
	/// <summary> The "Blue" drum velocity. </summary>
	unsigned char BlueVelocity;
	/// <summary> The "Orange" drum velocity. </summary>
	unsigned char OrangeVelocity;
	/// <summary> The "Yellow" drum velocity. </summary>
	unsigned char YellowVelocity;
	/// <summary> The Pedal velocity. </summary>
	unsigned char PedalVelocity;
	/// <summary> <c>True</c> if the "+" button is pressed. </summary>
	bool Plus;
	/// <summary> <c>True</c> if the "-" button is pressed. </summary>
	bool Minus;
	/// <summary> The drum joystick data. </summary>
	/// <seealso cref="wclWiiRemote2D" />
	wclWiiRemote2D Joystick;
} wclWiiRemoteDrums;

/// <summary> The structure describes the Wii Remote Balance Board extension
///   sensors data. </summary>
typedef struct
{
	/// <summary> Top right sensor value. </summary>
	unsigned short TopRight;
	/// <summary> Top left sensor value. </summary>
	unsigned short TopLeft;
	/// <summary> Bottom right sensor value. </summary>
	unsigned short BottomRight;
	/// <summary> Bottom left sensor value. </summary>
	unsigned short BottomLeft;
} wclWiiRemoteBalanceBoardSensors;

/// <summary> The structure describes the Wii Remote Balance Board extension
///   sensors weight. </summary>
typedef struct
{
	/// <summary> Top right sensor value. </summary>
	double TopRight;
	/// <summary> Top left sensor value. </summary>
	double TopLeft;
	/// <summary> Bottom right sensor value. </summary>
	double BottomRight;
	/// <summary> Bottom left sensor value. </summary>
	double BottomLeft;
} wclWiiRemoteBalanceBoardSensorsWeight;

/// <summary> The structure describes the Wii Remote Balance Board extension
///   sensors calibration data. </summary>
typedef struct
{
	/// <summary> The 0-17 KG calibration data. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensors" />
	wclWiiRemoteBalanceBoardSensors Kg0;
	/// <summary> The 17-34 KG calibration data. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensors" />
	wclWiiRemoteBalanceBoardSensors Kg17;
	/// <summary> The 34 and above KG calibration data. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensors" />
	wclWiiRemoteBalanceBoardSensors Kg34;
} wclWiiRemoteBalanceBoardCalibration;

/// <summary> The structure represents the Balance Board extension center of
///   gravity. </summary>
typedef struct
{
	/// <summary> An X coordinate. </summary>
	double X;
	/// <summary> An Y coordinate. </summary>
	double Y;
} wclWiiRemoteBalanceBoardGC;

/// <summary> The structure describes the Wii Remote Balance Board
///   extension. </summary>
typedef struct
{
	/// <summary> The Wii Remote Balance Board extension calibration
	///   data. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardCalibration" />
	wclWiiRemoteBalanceBoardCalibration Calibration;
	/// <summary> The Wii Remote Balance Board extension sensors
	///   values. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensors" />
	wclWiiRemoteBalanceBoardSensors Sensors;
	/// <summary> The Wii Remote Balance Board extension sensors values
	///   (KG). </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensorsWeight" />
	wclWiiRemoteBalanceBoardSensorsWeight SensorsKg;
	/// <summary> The Wii Remote Balance Board extension sensors values
	///   (Lb). </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardSensorsWeight" />
	wclWiiRemoteBalanceBoardSensorsWeight SensorsLb;
	/// <summary> The Wii Remote Balance Board extension detected weight
	///   (KG). </summary>
	double WeightKg;
	/// <summary> The Wii Remote Balance Board extension detected weight
	///   (Lb). </summary>
	double WeightLb;
	/// <summary> The center of gravity coordinate. </summary>
	/// <seealso cref="wclWiiRemoteBalanceBoardGC" />
	wclWiiRemoteBalanceBoardGC CenterOfGravity;
} wclWiiRemoteBalanceBoard;

/// <summary> The Bluetooth LE packet header. </summary>
typedef struct
{
	/// <summary> The access address. </summary>
	unsigned long AccessAddress;
	/// <summary> The channel number. </summary>
	unsigned char Channel;
	/// <summary> The CRC value. The CRC is 3 bytes long so hight byte is
	///   always 0x00. </summary>
	unsigned long Crc;
	/// <summary> The RSSI value in dBm. </summary>
	char Rssi;
	/// <summary> The time stamp value. </summary>
	unsigned long Timestamp;
	/// <summary> The packed valid status (<c>True</c> if the packet
	///   is valid. <c>False</c> otherwise. </summary>
	bool Valid;
} wclBluetoothLePacketHeader;

/// <summary> The Bluetooth LE advertising packet PDU types. </summary>
typedef enum
{
	/// <summary> The <c>ADV_IND</c> PDU type. </summary>
	ptAdvInd,
	/// <summary> The <c>ADV_DIRECT_IND</c> PDU type. </summary>
	ptAdvDirectInd,
	/// <summary> The <c>ADV_NONCONN_IND</c> PDU type. </summary>
	ptAdvNonConnInd,
	/// <summary> The <c>SCAN_REQ</c> PDU type. </summary>
	ptScanReq,
	/// <summary> The <c>AUX_SCAN_REQ</c> PDU type. </summary>
	ptAuxScanReq,
	/// <summary> The <c>SCAN_RSP</c> PDU type. </summary>
	ptScanRsp,
	/// <summary> The <c>CONNECT_IND</c> PDU type. </summary>
	ptConnectInd,
	/// <summary> The <c>AUX_CONNECT_REQ</c> PDU type. </summary>
	ptAuxConnectReq,
	/// <summary> The <c>ADV_SCAN_IND</c> PDU type. </summary>
	ptAdvScanInd,
	/// <summary> The <c>ADV_EXT_IND</c> PDU type. </summary>
	ptAdvExtInd,
	/// <summary> The <c>AUX_ADV_IND</c> PDU type. </summary>
	ptAuxAdvInd,
	/// <summary> The <c>AUX_SCAN_RSP</c> PDU type. </summary>
	ptAuxScanRsp,
	/// <summary> The <c>AUX_SYNC_IND</c> PDU type. </summary>
	ptAuxSyncInd,
	/// <summary> The <c>AUX_CHAIN_IND</c> PDU type. </summary>
	ptAuxChainInd,
	/// <summary> The <c>AUX_CONNECT_RSP</c> PDU type. </summary>
	ptAuxConnectRsp
} wclBluetoothLeAdvertisingPduType;

/// <summary> The record describes the Bluetooth LE advertising packet PDU
///   header. </summary>
typedef struct
{
	/// <summary> The Bluetooth LE captured packet header. </summary>
    /// <seealso cref="wclBluetoothLePacketHeader" />
	wclBluetoothLePacketHeader Header;
	/// <summary> The Bluetooth LE advertising PDU type. </summary>
	/// <seealso cref="wclBluetoothLeAdvertisingPduType" />
	wclBluetoothLeAdvertisingPduType PduType;
	/// <summary> The <c>ChSel</c> header's bit state. </summary>
	/// <remarks> The meaning of this field (bit) depends on the PDU type.
	///   If the value of this field is <c>True</c> the <c>ChSel</c> bit is
	///   <c>1</c>. If the value of this field is <c>Flase</c> the <c>ChSel</c>
	///   bit is <c>0</c>. </remarks>
	bool ChSel;
	/// <summary> The <c>TxAdd</c> header's bit state. </summary>
	/// <remarks> The meaning of this field (bit) depends on the PDU type.
	///   If the value of this field is <c>True</c> the <c>TxAdd</c> bit is
	///   <c>1</c>. If the value of this field is <c>Flase</c> the <c>TxAdd</c>
	///   bit is <c>0</c>. </remarks>
	bool TxAdd;
	/// <summary> The <c>RxAdd</c> header's bit state. </summary>
	/// <remarks> The meaning of this field (bit) depends on the PDU type.
	///   If the value of this field is <c>True</c> the <c>RxAdd</c> bit is
	///   <c>1</c>. If the value of this field is <c>Flase</c> the <c>RxAdd</c>
	///   bit is <c>0</c>. </remarks>
	bool RxAdd;
} wclBluetoothLeAdvertisingPduHeader;

/// <summary> The record contains the Link Layer data captured by the
///   Bluetooth LE sniffer and used in the <c>CONNECT_IND</c>
///  advertisement packet. </summary>
typedef struct
{
	/// <summary> The field contains the ACL connection’s Access Address
	///   determined by the Link Layer. </summary>
	unsigned long Aa;
	/// <summary> The field contains the initialization value for the CRC
	///   calculation for the ACL connection. It shall be a random value,
	///   generated by the Link Layer. The seed for the random number
	///   generator is from a physical source of entropy and has at least 20
	///   bits of entropy. </summary>
	unsigned long CrcInit;
	/// <summary> The field indicates the transmit window size value in the
	///   following manner: <c>WindowSize = WinSize * 1.25ms</c>. </summary>
	unsigned char WinSize;
	/// <summary> The field indicates the transmit window offset value in the
	///   following manner: <c>WindowOffset = WinOffset * 1.25ms</c>. </summary>
	unsigned short WinOffset;
	/// <summary> The field indicates the connection interval in the following
	///   manner: <c>ConnectionInterval = Interval * 1.25ms</c>. </summary>
	unsigned short Interval;
	/// <summary> The field indicates the peripheral latency value. </summary>
	unsigned short Latency;
	/// <summary> The field indicates the connection supervision timeout value
	///   in the following manner:
	///   <c>SupervisionTimeout = Timeout * 10ms</c>. </summary>
	unsigned short Timeout;
	/// <summary> The field contains the channel map indicating Used and Unused
	///   data channels. Every channel is represented with a bit positioned as
	///   per the data channel index. The <c>LSB</c> represents data channel
	///   index 0 and the bit in position 36 represents data channel index 36.
	///   A bit value of 0 indicates that the channel is Unused. A bit value of
	///   1 indicates that the channel is Used. The bits in positions 37, 38 and
	///   39 are reserved for future use. </summary>
	/// <remarks> The <c>ChM</c> value is 5 bytes long. The high 3 bytes are not
	///   used. </remarks>
	unsigned __int64 ChM;
	/// <summary> The field indicates the hop increment used in the data
	///   channel selection algorithm. It has a random value in the range 5 to
	///   16. </summary>
	unsigned char Hop;
	/// <summary> <p>The field indicates the central SCA used to determine the
	///   Central's worst case sleep clock accuracy. The value of the SCA
	///   are:</p>
	///   <p>0 - 251ppm to 500ppm</p>
	///   <p>1 - 151ppm to 250ppm</p>
	///   <p>2 - 101ppm to 150ppm</p>
	///   <p>3 - 76ppm to 100ppm</p>
	///   <p>4 - 51ppm to 75ppm</p>
	///   <p>5 - 31ppm to 50ppm</p>
	///   <p>6 - 21ppm to 30ppm</p>
	///   <p>7 - 0ppm to 20ppm</p> </summary>
	unsigned char Sca;
} wclBleSnifferLlData;

/* Event handler prototypes */

/// <summary> The <c>OnConfirm</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Confirm"> An application must set this parameter to
///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
///   pairing. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothConfirmEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, bool& Confirm)
/// <summary> The common event for notifications when a remote device's
///   MAC address required. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothDeviceEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address)
/// <summary> The common event handler prototype used for a remote
///   Bluetooth device's operations result notifications. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Error"> An operation result code. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothDeviceResultEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, const int Error)
/// <summary> The <c>OnIoCapabilityRequest</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Mitm"> An application sets this parameter to specify the
///   "Man in the Middle" protection required for authentication. </param>
/// <param name="IoCapability"> An application sets this parameter to define
///   the input/output capabilities of a Bluetooth Device. </param>
/// <param name="OobPresent"> An application sets this parameter to
///   <c>True</c> to force Out Of Band authentication. </param>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="wclBluetoothMitmProtection" />
/// <seealso cref="wclBluetoothIoCapability" />
#define wclBluetoothIoCapabilityRequestEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, wclBluetoothMitmProtection& Mitm, \
	wclBluetoothIoCapability& IoCapability, bool& OobPresent)
/// <summary> The common Bluetooth event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio)
/// <summary> The <c>OnNumericComparison</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Number"> A number sent by a remote device to display and
///   compare. </param>
/// <param name="Confirm"> An application must set this parameter to
///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
///   pairing. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothNumericComparisonEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, const unsigned long Number, bool& Confirm)
/// <summary> The <c>OnOobDataRequest</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="OobData"> An application must set this parameter to
///   the Out Of Band data received from peer device. </param>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="wclBluetoothOobData" />
#define wclBluetoothOobDataRequestEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, wclBluetoothOobData& OobData)
/// <summary> The <c>OnPasskeyNotification</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Passkey"> A Passkey provided by a remote
///   Bluetooth device. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothPasskeyNotificationEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, const unsigned long Passkey)
/// <summary> The <c>OnPasskeyRequest</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Passkey"> A Passkey provided by an application. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothPasskeyRequestEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, unsigned long& Passkey)
/// <summary> The <c>OnPinRequest</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Pin"> A PIN code provided by an application. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothPinRequestEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, tstring& Pin)
/// <summary> The <c>OnProtectionLevelRequest</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Address"> A remote device's MAC address. </param>
/// <param name="Protection"> Describes the required protection
///   level provided by an application. </param>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="wclBluetoothLeProtectionLevel" />
#define wclBluetoothProtectionLevelRequestEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const __int64 Address, wclBluetoothLeProtectionLevel& Protection)
/// <summary> The common Bluetooth result even handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
///   represents a Bluetooth driver that fired the event. </param>
/// <param name="Error"> An operation result code. </param>
/// <seealso cref="CwclBluetoothRadio" />
#define wclBluetoothResultEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclBluetoothRadio* const Radio, \
	const int Error)

/// <summary> The <c>GetSdpAttributes</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Protocols"> The additional protocol descriptors array that
///   should be added to SDP record. </param>
/// <param name="Profiles"> The profile descriptors list that should be added
///   to SDP record. </param>
/// <param name="Formats"> Other attributes that should be added to SDP
///   record. </param>
/// <param name="Cod"> <para> Class of device (COD) information. A 32-bit
///   parameter of COD_SERVICE_* class of device bits associated with this
///   SDP record. The system combines these bits with COD bits from other
///   service records and system characteristics. The resulting class of
///   device for the local radio is advertised when the radio is found during
///   device inquiry. When the last SDP record associated with a particular
///   service bit is deleted, that service bit is no longer reported in
///   responses to future device inquiries. </para>
///   <para> The format and possible values for the COD value are defined in
///   the Bluetooth Assigned Numbers 1.1 portion of the Bluetooth
///   specification, Section 1.2. (This resource may not be available in some
///   languages and countries.) </para> </param>
/// <seealso cref="wclBluetoothSdpProtocols" />
/// <seealso cref="wclBluetoothSdpProfiles" />
/// <seealso cref="wclBluetoothSdpFormats" />
#define wclBluetoothGetSdpAttributesEvent(_event_name_) \
	__event void _event_name_(void* Sender, wclBluetoothSdpProtocols& Protocols, \
	wclBluetoothSdpProfiles& Profiles, wclBluetoothSdpFormats& Formats, \
	unsigned long& Cod)

/// <summary> The prototype of the <c>OnConnect</c> event handler for RFCOMM
///   server. </summary>
/// <param name="Sender"> The object that initiated the event. </param>
/// <param name="Client"> The
///   <see cref="CwclRfCommServerClientConnection" /> represents a remote
///   connected client. </param>
/// <param name="Error"> The connection operation result code. If the
///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
///   device was established and the remote device is connected. Otherwise
///   the connection was not established and the remote device is
///   not connected. </param>
/// <seealso cref="CwclRfCommServerClientConnection" />
#define wclRfCommServerConnectEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclRfCommServerClientConnection* const Client, \
	const int Error)
/// <summary> A server connection <c>OnData</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object that initiated the event. </param>
/// <param name="Client"> A
///   <see cref="CwclRfCommServerClientConnection" /> object
///   represents a remote client connection. </param>
/// <param name="Data"> The pointer to the received data buffer.
///   It is guaranteed that the parameter points to a valid data buffer.
///   The data buffer is valid only inside the event handler. If an
///   application needs to use the data outside the event handle it must
///   allocate own buffer and copy data into it. </param>
/// <param name="Size"> The data buffer size. It is guaranteed that the size
///   is greater than 0. </param>
/// <seealso cref="CwclRfCommServerClientConnection" />
#define wclRfCommServerDataEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclRfCommServerClientConnection* const Client, \
	const void* const Data, const unsigned long Size)
/// <summary> The prototype of the <c>OnDisconnect</c> event handler for
///   server connections. </summary>
/// <param name="Sender"> The object that initiated the event. </param>
/// <param name="Client"> The
///   <see cref="CwclRfCommServerClientConnection" /> represents a remote
///   connected client. </param>
/// <param name="Reason"> The disconnection code. If the
///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
///   reason. </param>
/// <seealso cref="CwclRfCommServerClientConnection" />
#define wclRfCommServerDisconnectEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclRfCommServerClientConnection* const Client, \
	const int Reason)

/// <summary> The <c>OnCharacteristicChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Handle"> A changed characteristic handle. </param>
/// <param name="Value"> A pointer to the characteristic value. </param>
/// <param name="Length"> A characteristic value length in bytes. </param>
/// <remarks> The <c>Value</c> parameter is valid only inside the event
///   handler. If an application needs to use it outside the event handler
///   it must be copied. </remarks>
#define wclGattCharacteristicChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const unsigned short Handle, \
	const unsigned char* const Value, unsigned long const Length)

/// <summary> The <c>OnAdvertisementAppearanceFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Appearance"> The Bluetooth LE device appearance
///   value. </param>
#define wclBluetoothLeAdvertisementAppearanceFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned short Appearance)
/// <summary> The <c>OnAdvertisementFrameInformation</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Name"> The Bluetooth LE advertiser's name. </param>
/// <param name="PacketType"> The Bluetooth LE advertisement data packet
///   type. </param>
/// <param name="Flags"> The Bluetooth LE advertisement packet payload
///   flags. </param>
/// <seealso cref="wclBluetoothLeAdvertisementType" />
/// <seealso cref="wclBluetoothLeAdvertisementFlags" />
#define wclBluetoothLeAdvertisementFrameInformationEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const tstring& Name, \
	const wclBluetoothLeAdvertisementType PacketType, \
	const wclBluetoothLeAdvertisementFlags& Flags)
/// <summary> The <c>OnAdvertisementExtFrameInformation</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="AddressType"> The Bluetooth LE address type. </param>
/// <param name="TxPower"> The received transmit power of the
///   advertisement. Ranges from -127 dBm to 20 dBm. -128 indicates
///   "no value". </param>
/// <param name="Flags"> The Bluetooth LE advertisement extended frame
///   flags. </param>
/// <seealso cref="wclBluetoothAddressType" />
/// <seealso cref="wclBluetoothLeExtendedFrameFlags" />
#define wclBluetoothLeAdvertisementExtFrameInformationEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, const __int64 Timestamp, \
	const char Rssi, const wclBluetoothAddressType AddressType, const char TxPower, \
	const wclBluetoothLeExtendedFrameFlags& Flags)
/// <summary> The <c>OnAdvertisementRawFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="DataType"> The frame's data type. </param>
/// <param name="Data"> The frame's raw bytes data. If there is no data the
///   value is <c>NULL</c>. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAdvertisementRawFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned char DataType, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnAdvertisementReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Data"> The frame's raw bytes data. If there is no data the
///   value is <c>nil</c>. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAdvertisementReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnService16DataFrame</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 16 bits service UUID. </param>
/// <param name="Data"> The service data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAdvertisementService16DataFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned short Uuid, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnService32DataFrame</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 32 bits service UUID. </param>
/// <param name="Data"> The service data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAdvertisementService32DataFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned long Uuid, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnService128DataFrame</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 128 bits service UUID. </param>
/// <param name="Data"> The service data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAdvertisementService128DataFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const GUID& Uuid, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnServiceSol16Frame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 16 bits service UUID. </param>
#define wclBluetoothLeAdvertisementServiceSol16FrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned short Uuid)
/// <summary> The <c>OnServiceSol32Frame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 32 bits service UUID. </param>
#define wclBluetoothLeAdvertisementServiceSol32FrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned long Uuid)
/// <summary> The <c>OnServiceSol128Frame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The 128 bits service UUID. </param>
#define wclBluetoothLeAdvertisementServiceSol128FrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const GUID& Uuid)
/// <summary> The <c>OnAdvertisementTxPowerLevelFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="TxPower"> The TX power level in range from -127 to 128
///   dBm. </param>
#define wclBluetoothLeAdvertisementTxPowerLevelFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const char TxPower)
/// <summary> The <c>OnAdvertisementUuidFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="Uuid"> The advertised UUID value. </param>
#define wclBluetoothLeAdvertisementUuidFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const GUID& Uuid)
/// <summary> The <c>OnAltBeaconFrame</c> event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
///   Bluetooth SIG Assigned Numbers. </param>
/// <param name="Major"> The beacon's Major value. </param>
/// <param name="Minor"> The beacon's Minor value. </param>
/// <param name="Uuid"> The beacon's UUID. </param>
/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
///   distance. </param>
/// <param name="Reserved"> A 1-byte value from 0x00 to 0xFF. Interpretation
///   of this value is to be defined by the manufacturer and is to be
///   evaluated based on the CompanyId value. </param>
/// <param name="Data"> The additional frame data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeAltBeaconFrameEvent(_event_name_) \
	__event void _event_name_(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)
/// <summary> The <c>OnEddystoneTlmFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="AdvCnt"> The running count of advertisement frames of all
///   types emitted by the beacon since power-up or reboot, useful for
///   monitoring performance metrics that scale per broadcast frame.
///   If this value is reset (e.g. on reboot), the current time field is
///   also reset. </param>
/// <param name="Batt"> The current battery charge in millivolts, expressed as
///   1 mV per bit. If not supported (for example in a USB-powered beacon) the
///   value should be zeroed. </param>
/// <param name="SecCnt"> The 0.1 second resolution counter that represents
///   time since beacon power-up or reboot. If this value is reset (e.g. on
///   a reboot), the AdvCnt count field is also reset. </param>
/// <param name="Temp"> The beacon temperature in degrees Celsius sensed by
///   the beacon. If not supported the value is -128 °C. </param>
/// <param name="Data"> The additional frame data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeEddystoneTlmFrameEvent(_event_name_) \
	__event void _event_name_(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)
/// <summary> The <c>OnEddystoneUidFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
///   distance. </param>
/// <param name="Uuid"> The Eddystone ID: 10 bytes - Namespace ID and 6
///   bytes - Instance ID. </param>
/// <param name="Data"> The additional frame data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeEddystoneUidFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const char TxRssi, const GUID& Uuid, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnEddystoneUrlFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
///   distance. </param>
/// <param name="Url"> The Eddystone URL. </param>
#define wclBluetoothLeEddystoneUrlFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const char TxRssi, \
	const tstring& Url)
/// <summary> The <c>OnManufacturerRawFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
///   Bluetooth SIG Assigned Numbers. </param>
/// <param name="Data"> The frame raw data. The value can be <c>NULL</c> if
///   there is no any data available in the frame. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeManufacturerRawFrameEvent(_event_name_) \
	__event void _event_name_(void* Sender, const __int64 Address, \
	const __int64 Timestamp, const char Rssi, const unsigned short CompanyId, \
	const wclBluetoothLeAdvertisementFrameRawData& Data)
/// <summary> The <c>OnProximityBeaconFrame</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
/// <param name="Timestamp"> The frame's timestamp in Universal Time
///   format. </param>
/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution. </param>
/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
///   Bluetooth SIG Assigned Numbers. </param>
/// <param name="Major"> The beacon's Major value. </param>
/// <param name="Minor"> The beacon's Minor value. </param>
/// <param name="Uuid"> The beacon's UUID. </param>
/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
///   distance. </param>
/// <param name="Data"> The additional frame data. </param>
/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
#define wclBluetoothLeProximityBeaconFrameEvent(_event_name_) \
	__event void _event_name_(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 wclBluetoothLeAdvertisementFrameRawData& Data)

/// <summary> The GATT server client event handlers prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
///   represents a GATT server client. </param>
/// <remarks> This event handler prototype is used for
///   <c>OnClientConnected</c> and <c>OnClientDisconnected</c> events of the
///   GATT server. </remarks>
/// <seealso cref="CwclGattServerClient" />
#define wclGattServerClientEvent(_event_name_) \
	__event void _event_name_(void* Sender, CwclGattServerClient* const Client)
/// <summary> The <c>OnRead</c> characteristic's event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
///   requested read. </param>
/// <param name="Characteristic"> The characteristic object for which writes
///   is executing. </param>
/// <param name="Request"> The GATT read request object. </param>
/// <seealso cref="CwclGattServerClient" />
/// <seealso cref="CwclGattLocalCharacteristic" />
/// <seealso cref="TwclGattLocalCharacteristicReadRequest" />
#define wclGattLocalCharacteristicReadEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	CwclGattServerClient* const Client, \
	CwclGattLocalCharacteristic* const Characteristic, \
	CwclGattLocalCharacteristicReadRequest* const Request)
/// <summary> The <c>OnWrite</c> characteristic's event handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
///   requested write. </param>
/// <param name="Characteristic"> The characteristic object for which writes
///   is executing. </param>
/// <param name="Request"> The GATT characteristic write request object. </param>
/// <seealso cref="CwclGattServerClient" />
/// <seealso cref="CwclGattLocalCharacteristic" />
/// <seealso cref="TwclGattLocalCharacteristicWriteRequest" />
#define wclGattLocalCharacteristicWriteEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	CwclGattServerClient* const Client, \
	CwclGattLocalCharacteristic* const Characteristic, \
	CwclGattLocalCharacteristicWriteRequest* const Request)
/// <summary> The <c>OnClientSubscribed</c> and <c>OnClientUnsubscribed</c>
///   events handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
///   subscribed or unsubscribed. </param>
/// <param name="Characteristic"> The characteristic object for which writes
///   is executing. </param>
/// <seealso cref="CwclGattServerClient" />
/// <seealso cref="CwclGattLocalCharacteristic" />
#define wclGattLocalCharacteristicSubscribedClientsChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	CwclGattServerClient* const Client, CwclGattLocalCharacteristic* const Characteristic)

/// <summary> The Wii Remote <c>OnAccelChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Accel"> The current accelerometer data. </param>
/// <seealso cref="wclWiiRemoteAccel" />
#define wclWiiRemoteAccelChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteAccel& Accel)
/// <summary> The Wii Remote <c>OnBalanceBoardChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Board"> The new Balance Board extension
///   state. </param>
/// <seealso cref="wclWiiRemoteBalanceBoard" />
#define wclWiiRemoteBalanceBoardChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteBalanceBoard& Board)
/// <summary> The Wii Remote <c>OnButtonsChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Buttons"> The current state of the Wii Remote controller
///   buttons. </param>
/// <seealso cref="wclWiiRemoteButtons" />
#define wclWiiRemoteButtonsChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteButtons& Buttons)
/// <summary> The Wii Remote <c>OnClassicControllerChanged</c> event
///   handler prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Controller"> The current state of the Wii Remote Classic
///   Controller extension. </param>
/// <seealso cref="wclWiiRemoteClassicController" />
#define wclWiiRemoteClassicControllerChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteClassicController& Controller)
/// <summary> The Wii Remote <c>OnDrumsChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Drums"> The current state of the Drums extension. </param>
/// <seealso cref="wclWiiRemoteDrums" />
#define wclWiiRemoteDrumsChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteDrums& Drums)
/// <summary> The Wii Remote <c>OnGuitarChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Guitar"> The current Guitar extension state. </param>
/// <seealso cref="wclWiiRemoteGuitar" />
#define wclWiiRemoteGuitarChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteGuitar& Guitar)
/// <summary> The Wii Remote <c>OnIrChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Ir"> The IR sensor data. </param>
/// <seealso cref="wclWiiRemoteIrSensors" />
#define wclWiiRemoteIrChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteIrSensors& Ir)
/// <summary> The Wii Remote <c>OnNunchukChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Nunchuk"> The current Nunchuk extension state. </param>
/// <seealso cref="wclWiiRemoteNunchuk" />
#define wclWiiRemoteNunchukChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const wclWiiRemoteNunchuk& Nunchuk)
/// <summary> The Wii Remote <c>OnStatusChanged</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Batt"> The WeDo Remote battery level. </param>
/// <param name="Leds"> The We Do Remote LEDs state. </param>
/// <seealso cref="wclWiiRemoteLeds" />
#define wclWiiRemoteStatusChangedEvent(_event_name_) \
	__event void _event_name_(void* Sender, const double Batt, \
	const wclWiiRemoteLeds& Leds)

/// <summary> The BLE sniffer <c>OnAdvDirectIndReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="AdvA"> The advertiser address. </param>
/// <param name="TargetA"> The address of the device to which this PDU
///   is addressed. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>AdvA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True).
///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
///   whether the target’s address in the <c>TargetA</c> parameter is
///   public (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c> field
///   in the <c>PduHeader</c> parameter is <c>True</c> if the advertiser
///   supports the LE Channel Selection Algorithm #2 feature. </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferAdvDirectIndReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 AdvA, const __int64 TargetA)
/// <summary> The BLE sniffer <c>OnAdvIndReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="AdvA"> The advertiser address. </param>
/// <param name="AdvData"> The pointer to the advertisement data.
///   Can be <c>NULL</c>. The pointer is valid only inside the event
///   handler. </param>
/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>AdvA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True). The
///   <c>ChSel</c> field in the <c>PduHeader</c> parameter is <c>True</c>
///   if the advertiser supports the LE Channel Selection Algorithm #2
///   feature. </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferAdvIndReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 AdvA, const unsigned char* const AdvData, \
	const unsigned char AdvDataLen)
/// <summary> The BLE sniffer <c>OnAdvNonConnIndReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="AdvA"> The advertiser address. </param>
/// <param name="AdvData"> The pointer to the advertisement data.
///   Can be <c>NULL</c>. The pointer is valid only inside the event
///   handler. </param>
/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>AdvA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferAdvNonConnIndReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 AdvA, const unsigned char* const AdvData, \
	const unsigned char AdvDataLen)
/// <summary> The BLE sniffer <c>OnAdvScanIndReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="AdvA"> The advertiser address. </param>
/// <param name="AdvData"> The pointer to the advertisement data.
///   Can be <c>NULL</c>. The pointer is valid only inside the event
///   handler. </param>
/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>AdvA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferAdvScanIndReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 AdvA, const unsigned char* const AdvData, \
	const unsigned char AdvDataLen)
/// <summary> The BLE sniffer <c>OnConnectIndReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="InitA"> The Initiator’s device address. </param>
/// <param name="AdvA"> The advertiser’s device address. </param>
/// <param name="LlData"> The Link Layer data. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>InitA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True). The
///   <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates whether
///   the advertiser’s device address in the <c>AdvA</c> parameter is public
///   (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c> field in the
///   <c>PduHeader</c> parameter is <c>True</c> if the advertiser supports the
///   LE Channel Selection Algorithm #2 feature. </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
/// <seealso cref="wclBleSnifferLlData" />
#define wclBleSnifferConnectIndReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 InitA, const __int64 AdvA, \
	const wclBleSnifferLlData& LlData)
/// <summary> The BLE sniffer <c>OnScanReqReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="ScanA"> The scanner's address. </param>
/// <param name="AdvA"> The address of the device to which this PDU
///   is addressed. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the scanner’s address in the <c>ScanA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True).
///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
///   whether the target’s address in the <c>AdvA</c> parameter is
///   public (RxAdd = False) or random (RxAdd = True). </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferScanReqReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 ScanA, const __int64 AdvA)
/// <summary> The BLE sniffer <c>OnScanRspReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="PduHeader"> The PDU header. </param>
/// <param name="AdvA"> The advertiser address. </param>
/// <param name="ScanRspData"> The pointer to the advertisement data.
///   Can be <c>NULL</c>. The pointer is valid only inside the event
///   handler. </param>
/// <param name="ScanRspDataLen"> The advertisement data length in
///   bytes. </param>
/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
///   indicates whether the advertiser’s address in the <c>AdvA</c>
///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
#define wclBleSnifferScanRspReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLeAdvertisingPduHeader& PduHeader, \
	const __int64 AdvA, const unsigned char* const ScanRspData, \
	const unsigned char ScanRspDataLen)
/// <summary> The BLE sniffer <c>OnRawPacketReceived</c> event handler
///   prototype. </summary>
/// <param name="Sender"> The object initiates the event. </param>
/// <param name="Header"> The Bluetooth LE packet header. </param>
/// <param name="Payload"> The pointer to the packet's payload raw bytes.
///   The pointer is valid only inside an event handler. If an application
///   needs to use the data outside the event handler it must copy the
///   payload. </param>
/// <param name="Size"> The payload size (length) in bytes. </param>
/// <seealso cref="wclBluetoothLePacketHeader" />
#define wclBleSnifferRawPacketReceivedEvent(_event_name_) \
	__event void _event_name_(void* Sender, \
	const wclBluetoothLePacketHeader& Header, \
	const unsigned char* const Payload, const unsigned short Size)

/* General Bluetooth classes and components */

/// <summary> Supported connection types. </summary>
typedef enum
{
	/// <summary> RFCOMM client connection. </summary>
	ctRfCommClient,
	/// <summary> RFCOMM server connection. </summary>
	ctRfCommServer,
	/// <summary> BLE GATT client connection. </summary>
	ctGattClient,
	/// <summary> BLE GATT server connection. </summary>
	ctGattServer,
	/// <summary> BLE beacon watcher connection. </summary>
	ctBeaconWatcher,
	/// <summary> Bluetooth LE advertiser connection. </summary>
	ctLeAdvertiser,
	/// <summary> Wii Remote controller client connection. </summary>
	ctWiiRemote
} wclBluetoothConnectionType;

/// <summary> The class represents a local Bluetooth radio module. </summary>
/// <remarks> <para> An application must never create or destroy this class
///   directly. Instead of that an application must use methods of the
///   <see cref="CwclBluetoothManager" /> component. </para>
///   <para> The class is thread safe. </para>
///   <para> The only single instance of the class for each supported
///   Bluetooth driver can be created. </para> </remarks>
/// <seealso cref="CwclBluetoothManager" />
class CwclBluetoothRadio
{
	DISABLE_COPY(CwclBluetoothRadio);

private:
	friend class CwclRfCommClient;
	friend class CwclRfCommServer;
	friend class CwclGattClient;
	friend class CwclGattServer;
	friend class CwclBluetoothLeAdvertiser;
	friend class CwclBluetoothLeBeaconWatcher;
	friend class CwclWiiRemoteClient;

	typedef std::list<CwclCustomConnection*>	CONNECTIONS;

	friend class CwclBluetoothManager;

	// This flag used internally when processing radio state changes messages
	// to protect from same state processing.
	bool						FAvailable;
	// This critical section used as synchronization object for
	// the Radio members and the API manages local Radio settings.
	// It is initialized in the constructor and releases in the destructor.
	RTL_CRITICAL_SECTION		FCS;
	// Discovering flag.
    bool						FDiscovering;
	// Indicates that discovering started message has been received.
	bool						FDiscoveringStarted;
	// The Radio instance protection mutex handle. This mutex created during
	// a Radio object initialization. The mutex is unique per process. If other
	// instance of the Radio class already exists the mutex creation fails and a
	// Bluetooth driver supported by the Radio object will not be initialized.
	HANDLE						FInstance;
	// Indicates LE discovering.
	bool						FLeDiscovering;
	// The loaded flag set when a Bluetooth driver supported by the Radio
	// object has been loaded and initialized.
	bool						FLoaded;
	// The Bluetooth Manager object that owns the Radio.
	CwclBluetoothManager*		FManager;
	// The address of manually pairing device.
	__int64						FPairAddress;
	// The manual pairing operation flag.
	bool						FPairing;
	// Internal flag indicates if the radio hardware is plugged.
	bool						FPlugged;
	// This message receiver created in the constructor. The message receiver is
	// used by the Radio object to receive notifications from a supported
	// Bluetooth driver.
	CwclMessageReceiver*		FReceiver;
	// Used during discovering to filter duplicated devices.
	wclBluetoothAddresses		FFoundDevices;
	// Flag indicates that paired devices must be reported as found even they
	// are not available.
	bool						FIncludePaired;

	CONNECTIONS*				FConnections;
	wclVirtualComPorts			FComPorts;

	// This function initializes the global radio instance mutex.
    int InitializeGlobalInstanceMutex();
	// The function checks if radio supports Bluetooth LE functions. Returns
    // WCL_E_SUCCESS if yes, error otherwise.
    int IsBluetoothLeSupported();

	// Tests if the classic device with given MAC was not found.
    bool DeviceNotFound(const __int64 Address);

	/* Cleanup */

	void CloseAllConnections(const int Reason);
	void DestroyComPorts();

	/* Connections management. */
	
	int CreateConnection(const wclBluetoothConnectionType ConnectionType,
		CwclCustomConnection*& Connection);
	void RegisterConnection(CwclCustomConnection* const Connection, const int Result);
	void RemoveConnection(CwclCustomConnection* const Connection);
	
	/* Radio control methods. */
	
	// This method is called by the Bluetooth Manager when releasing the Radio
	// object. It is guaranteed by the Bluetooth Manager that call to this
	// method is synchronized.
	int Close();
	// This method is called by the Bluetooth Manager to initialize the Radio
	// object and load the supported Bluetooth driver. If call to this method
	// failed the Bluetooth Manager must immediately destroy the Radio object.
	// It is guaranteed by the Bluetooth Manager that call to this method
	// is synchronized.
	int Open();

	/* Message processing. */

    void ProcessStatusChangedMessage();
	void ProcessDiscoveringStartedMessage();
	void ProcessDiscoveringCompletedMessage(const int Error);
	void ProcessDeviceFoundMessage(const CwclMessage* const Message);
	void ProcessIoCapRequestMessage(const __int64 Address);
	void ProcessProtectionRequestMessage(const __int64 Address);
	void ProcessPinRequestMessage(const __int64 Address);
	void ProcessNumericComparisonMessage(const __int64 Address,
		const unsigned long Number);
	void ProcessPasskeyRequestMessage(const __int64 Address);
	void ProcessPasskeyNotificationMessage(const __int64 Address,
		const unsigned long Passkey);
	void ProcessConfirmOnlyMessage(const __int64 Address);
	void ProcessOobDataRequestMessage(const __int64 Address);
	void ProcessAuthCompletedMessage(const __int64 Address, const int Error);
	
protected:
	/* Internal methods. */
	
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message);
	
	/// <summary> Fires the <c>OnAuthenticationCompleted</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Error"> An operation result code. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	virtual void DoAuthenticationCompleted(const __int64 Address, const int Error);
	/// <summary> Fires the <c>OnConfirm</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	virtual void DoConfirm(const __int64 Address, bool& Confirm);
	/// <summary> Fires the <c>OnDeviceFound</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	virtual void DoDeviceFound(const __int64 Address);
	/// <summary> Fires the <c>OnDiscoveringCompleted</c> event. </summary>
	/// <param name="Error"> An operation result code. </param>
	virtual void DoDiscoveringCompleted(const int Error);
	/// <summary> Fires the <c>OnDiscoveringStarted</c> event. </summary>
	virtual void DoDiscoveringStarted();
	/// <summary> Fires the <c>OnIoCapabilityRequest</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Mitm"> An application sets this parameter to specify the
	///   "Man in the Middle" protection required for authentication. </param>
	/// <param name="IoCapability"> An application sets this parameter to define
	///   the input/output capabilities of a Bluetooth Device. </param>
	/// <param name="OobPresent"> An application sets this parameter to
	///   <c>True</c> to force Out Of Band authentication. </param>
	/// <seealso cref="wclBluetoothMitmProtection" />
	/// <seealso cref="wclBluetoothIoCapability" />
	virtual void DoIoCapabilityRequest(const __int64 Address,
		wclBluetoothMitmProtection& Mitm, wclBluetoothIoCapability& IoCapability,
		bool& OobPresent);
	/// <summary> Fires the <c>OnNumericComparison</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Number"> A number sent by a remote device to display and
	///   compare. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	virtual void DoNumericComparison(const __int64 Address,
		const unsigned long Number, bool& Confirm);
	/// <summary> Fires the <c>OnOobDataRequest</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="OobData"> An application must set this parameter to
	///   the Out Of Band data received from peer device. </param>
	/// <seealso cref="wclBluetoothOobData" />
	virtual void DoOobDataRequest(const __int64 Address, wclBluetoothOobData& OobData);
	/// <summary> Fores the <c>OnPasskeyNotification</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Passkey"> A Passkey provided by a remote
	///   Bluetooth device. </param>
	virtual void DoPasskeyNotification(const __int64 Address, const unsigned long Passkey);
	/// <summary> Fires the <c>OnPasskeyRequest</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Passkey"> A passkey provided by an application. </param>
	virtual void DoPasskeyRequest(const __int64 Address, unsigned long& Passkey);
	/// <summary> Fires the <c>OnPinRequest</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Pin"> A PIN code provided by an application. </param>
	virtual void DoPinRequest(const __int64 Address, tstring& Pin);
	/// <summary> Fires the <c>OnProtectionLevelRequest</c> event. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Protection"> Describes the required protection
	///   level provided by an application. </param>
	/// <remarks> This method is used only during BLE pairing. </remarks>
	/// <seealso cref="wclBluetoothLeProtectionLevel" />
	virtual void DoProtectionLevelRequest(const __int64 Address,
		wclBluetoothLeProtectionLevel& Protection);
	/// <summary> Fires the <c>OnStatusChanged</c> event. </summary>
	virtual void DoStatusChanged();
	
	/* HAL initialization. */
	
	/// <summary> Implements a driver-dependent code for getting API
	///   functions pointers. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalGetFunctions() = 0;
	/// <summary> Implements a driver-dependent code for API
	///   initialization. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalInitialize() = 0;
	/// <summary> Implements a driver-dependent code for loading API
	///   DLLs. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalLoadApi() = 0;
	/// <summary> Implements a driver-dependent code for callback
	///   registration. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalRegisterCallbacks() = 0;
	/// <summary> Implements a driver-dependent code for setting the Radio object
	///   global instance variable. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalSetGlobalInstance() = 0;

	/* HAL finalization. */
	
	/// <summary> Implements a driver-dependent code for API functions
	///   clearing. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalClearFunctions() = 0;
	/// <summary> Implements a driver-dependent code for clearing the
	///   global instance of the Radio object. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalClearGlobalInstance() = 0;
	/// <summary> Implements a driver-dependent code for pending operation
	///   termination. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalTerminateOperations() = 0;
	/// <summary> Implements a driver-dependent code for driver
	///   uninitialization. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalUninitialize() = 0;
	/// <summary> Implements a driver-dependent code for API
	///   unloading. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalUnloadApi() = 0;
	/// <summary> Implements a driver-dependent code for callbacks
	///   unregistering. </summary>
	/// <remarks> A derived class must override this method. </remarks>
	virtual void HalUnregisterCallbacks() = 0;

	/* HAL local Radio methods. */
	
	/// <summary> Implements a hardware-dependent code for Local Bluetooth
	///   Radio module MAC address reading. </summary>
	/// <param name="Address"> On output the local Bluetooth Radio
	///   address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetAddress(__int64& Address) = 0;
	/// <summary> Implements a hardware-dependent code for Local Bluetooth
	///   Radio module Class Of Device (COD) reading. </summary>
	/// <param name="Cod"> On output the local Bluetooth Radio COD. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalGetCod(unsigned long& Cod) = 0;
	/// <summary> Implements a hardware-dependent code for reading the local
	///   Bluetooth Radio connectable state. </summary>
	/// <param name="Connectable"> On output the local Bluetooth Radio
	///   connectable state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetConnectable(bool& Connectable) = 0;
	/// <summary> Implements a hardware-dependent code to read the local
	///   Bluetooth Radio discoverable state. </summary>
	/// <param name="Discoverable"> On output the local Bluetooth Radio
	///   discoverable state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetDiscoverable(bool& Discoverable) = 0;
	/// <summary> Implements a hardware-dependent code to reads the HCI version
	///   of the local Radio module. </summary>
	/// <param name="Version"> On output the HCI version number. </param>
	/// <param name="Revision"> On output the HCI revision number. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetHciVersion(unsigned char& Version, unsigned short& Revision) = 0;
	/// <summary> Implements a hardware-dependent code to reading the LMP version
	///   of the local Radio module. </summary>
	/// <param name="Version"> On output the LMP version number. </param>
	/// <param name="Subversion"> On output the LMP subversion number. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetLmpVersion(unsigned char& Version, unsigned short& Subversion) = 0;
	/// <summary> Implements a hardware-dependent code to read the Bluetooth
	///   Radio manufacturer ID. </summary>
	/// <param name="Manu"> On output the manufacturer ID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetManufacturer(unsigned short& Manu) = 0;
	/// <summary> Implements a hardware-dependent code for reading the local
	///   Radio name. </summary>
	/// <param name="Name"> On output the local Bluetooth Radio
	///   name. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetName(tstring& Name) = 0;
	
	/// <summary> Implements a hardware-dependent code to changing the
	///   local Bluetooth Radio Class Of Device (COD). </summary>
	/// <param name="Cod"> The new local Bluetooth Radio COD. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalSetCod(const unsigned long Cod) = 0;
	/// <summary> Implements a hardware-dependent code to changing the
	///   connectable state of the local Bluetooth Radio. </summary>
	/// <param name="Connectable"> The new connectable state for the
	///   Radio. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalSetConnectable(const bool Connectable) = 0;
	/// <summary> Implements a hardware-dependent code for changing the
	///   discoverable state of the local Bluetooth Radio. </summary>
	/// <param name="Discoverable"> The new discoverable state for the
	///   Radio. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalSetDiscoverable(const bool Discoverable) = 0;
	/// <summary> Implements a hardware-dependent code for changing the local
	///   Bluetooth Radio module name. </summary>
	/// <param name="Name"> The new Radio name. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalSetName(const tstring& Name) = 0;

	/// <summary> The method turns the local Bluetooth radio ON. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalTurnOn() = 0;
	/// <summary> The method turns the local Bluetooth radio OFF. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalTurnOff() = 0;

	/* HAL remote devices discovering. */
	
	/// <summary> Implements a hardware-dependent code to start discovering for a
	///   remote Classic Bluetooth devices. </summary>
	/// <param name="Timeout"> Specifies the maximum amount of time before
	///   the inquiry is halted (in seconds). </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalDiscoverClassic(const unsigned char Timeout) = 0;
    /// <summary> Implements a hardware-dependent code to start discovering for a
    ///   remote Low Energy Bluetooth devices. </summary>
    /// <param name="Timeout"> Specifies the maximum amount of time before
    ///   the inquiry is halted (in seconds). </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   a driver-dependent code. </remarks>
    virtual int HalDiscoverBle(const unsigned char Timeout) = 0;
	/// <summary> Implements a hardware-dependent code for discovering
	///   termination. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalTerminate() = 0;

	/// <summary> Implements a hardware-dependent code for paired devices
	///   enumerating. </summary>
	/// <param name="Devices"> On output the dynamic array will be filled with
	///   pared devices MACs. A caller is responsible to free the memory
	///   allocated (if was) for this parameter. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalEnumPairedDevices(wclBluetoothAddresses& Devices) = 0;
	/// <summary> Implements a hardware-dependent code for connected devices
	///   enumerating. </summary>
	/// <param name="Devices"> On output the dynamic array will be filled with
	///   connected devices MACs. A caller is responsible to free the memory
	///   allocated (if was) for this parameter. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalEnumConnectedDevices(wclBluetoothAddresses& Devices) = 0;

	/// <summary> Implements a hardware-dependent code for reading the available
	///   services from a remote Bluetooth device. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Uuid"> The pointer to a service's UUID. If an application
	///   need to get information about specific service it set this
	///   parameter to a valid pointer to the required service's UUID.
	///   If this parameter is <c>NULL</c> the information about all available
	///   services will be returned. </param>
	/// <param name="Services"> On output the remote Bluetooth device
	///   services list. An application is responsible to free a memory
	///   allocated for the array. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalEnumRemoteServices(const __int64 Address, const GUID* const Uuid,
		wclBluetoothServices& Services) = 0;

	/// <summary> Implements a hardware-dependent code to check if a remote
	///   device is in range. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="InRange"> If the function completed with success
	///   indicates if a remote device is in range. <c>True</c> if a remote
	///   device is in range. <c>False</c> otherwise. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalIsRemoteDeviceInRange(const __int64 Address, bool& InRange) = 0;

	/// <summary> Implements a hardware-dependent code to disconnect a remote
	///   device. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalRemoteDisconnect(const __int64 Address) = 0;

	/* HAL remote device functions. */

	/// <summary> Implements a hardware-dependent code for reading a remote
	///   device address type. </summary>
	/// <param name="Address"> A remote Bluetooth enabled device's MAC
	///   address. </param>
	/// <param name="AddrType"> On output a remote device's Address
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothAddressType" />
	virtual int HalGetRemoteAddressType(const __int64 Address,
		wclBluetoothAddressType& AddrType) = 0;
	/// <summary> Implements a hardware-dependent code for reading a remote
	///   device COD (Class Of Device). </summary>
	/// <param name="Address"> A remote Bluetooth enabled device's MAC
	///   address. </param>
	/// <param name="Cod"> On output a remote device's COD. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetRemoteCod(const __int64 Address, unsigned long& Cod) = 0;
	/// <summary> Implements a hardware-dependent code to reading a remote
	///   Bluetooth device type. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="DevType"> On output a remote Bluetooth device
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothDeviceType" />
	virtual int HalGetRemoteDeviceType(const __int64 Address,
		wclBluetoothDeviceType& DevType) = 0;
	/// <summary> Implements a hardware-dependent code for querying a remote
	///   device's name. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Name"> On output a remote device's name. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetRemoteName(const __int64 Address, tstring& Name) = 0;
	/// <summary> Implements a hardware-dependent code for reading a remote
	///   Bluetooth device paired status. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Paired"> On output a remote Bluetooth device paired status.
	///   if <c>True</c> a remote device has been paired with this
	///   Radio. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetRemotePaired(const __int64 Address, bool& Paired) = 0;

	/// <summary> The function checks if the specified remote device is
	///   currently connected. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Connected"> On output the connected status of the
	///   remote device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetRemoteConnectedStatus(const __int64 Address, bool& Connected) = 0;
	/// <summary> Reads RSSI value from a remote device. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Rssi"> On output contains the RSSI value in dBm. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalGetRemoteRssi(const __int64 Address, char& Rssi) = 0;

	/* HAL Authentication reply. */
	
	/// <summary> Implements a hardware-dependent code to reply on a
	///   confirm only pairing request. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalConfirmReply(const __int64 Address, const bool Confirm) = 0;
	/// <summary> Implements a hardware-dependent code to reply on an
	///   IO capability request. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Mitm"> Specifies the "Man in the Middle" protection
	///   required for authentication. </param>
	/// <param name="IoCapability"> Defines the input/output capabilities of a
	///   Bluetooth Device. </param>
	/// <param name="OobPresent"> If this parameter is <c>True</c> the Out Of
	///   Band authentication will be executed. </param>
	/// <seealso cref="wclBluetoothMitmProtection" />
	/// <seealso cref="wclBluetoothIoCapability" />
	virtual int HalIoCapabilityReply(const __int64 Address,
		const wclBluetoothMitmProtection Mitm,
		const wclBluetoothIoCapability IoCapability, const bool OobPresent) = 0;
	/// <summary> Implements a hardware-dependent code to reply on a
	///   numeric comparison request. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Value"> The numeric value reply. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalNumericComparisonReply(const __int64 Address,
		const unsigned long Value, const bool Confirm) = 0;
	/// <summary> Implements a hardware-dependent code to reply on a
	///   Out Of Band pairing request. </summary>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="OobData"> An Out Of Band pairing data. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothOobData" />
	virtual int HalOobDataReply(const __int64 Address,
		const wclBluetoothOobData& OobData) = 0;
	/// <summary> Implements a hardware-dependent code to reply for a
	///   passkey request event. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Passkey"> A Passkey provided by an application. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalPasskeyReply(const __int64 Address, const unsigned long Passkey) = 0;
	/// <summary> Implements a hardware-dependent code to reply for a
	///   PIN request event. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Pin"> A PIN code provided by an application. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	virtual int HalPinReply(const __int64 Address, const tstring& Pin) = 0;
	/// <summary> Implements a hardware-dependent code to reply for a
	///   pairing protection level request event. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Protection"> A pairing protection level. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothLeProtectionLevel" />
	virtual int HalProtectionLevelReply(const __int64 Address,
		const wclBluetoothLeProtectionLevel Protection) = 0;

	/* HAL authentication. */
	
	/// <summary> Implements a hardware-dependent code for pairing with a remote
	///   Bluetooth device. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Method"> The pairing method. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothPairingMethod" />
	virtual int HalRemotePair(const __int64 Address,
		const wclBluetoothPairingMethod Method) = 0;
	/// <summary> Implements a hardware-dependent code to unpair a remote
	///   Bluetooth device. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="Method"> The unpairing method. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   a driver-dependent code. </remarks>
	/// <seealso cref="wclBluetoothPairingMethod" />
	virtual int HalRemoteUnpair(const __int64 Address,
		const wclBluetoothPairingMethod Method) = 0;
	
	/* HAL Secure Simple Pairing management. */
	
	/// <summary> Implements a hardware-dependent code that reads a radio
	///   Secure Simple Pairing mode. </summary>
	/// <param name="Enabled"> If the function completed with success on output
	///   contains a boolean that indicates the current Secure Simple Pairing
	///   (SSP) mode. <c>True</c> if SSP is enabled. <c>False</c> if SSP is
	///   disabled. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalGetSimplePairingMode(bool& Enabled) = 0;
	/// <summary> Implements a hardware-dependent code that writes a radio
	///   Secure Simple Pairing mode. </summary>
	/// <param name="Enable"> A boolean that indicates the new Secure Simple
	///   Pairing (SSP) mode. Set this parameter to <c>True</c> to enable SSP.
	///   Set this parameter to <c>False</c> to disable SSP. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver-dependent code. </remarks>
	virtual int HalSetSimplePairingMode(const bool Enable) = 0;

	/* HAL connections management. */
	
	/// <summary> Creates a hardware-dependent connection object based on
    ///   connection type. </summary>
    /// <param name="ConnectionType"> A type of the required connection
    ///   object. </param>
	/// <param name="Connection"> If the function completed with success on
	///   output contains the connection object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothConnectionType" />
	/// <seealso cref="CwclCustomConnection" />
	virtual int HalCreateConnection(const wclBluetoothConnectionType ConnectionType,
		CwclCustomConnection*& Connection) = 0;
	
	/* Virtual COM ports management. */

    /// <summary> Creates new virtual COM port. </summary>
    /// <param name="Address"> Remote device address. </param>
    /// <param name="Service"> A service's UUID. </param>
    /// <param name="Number"> If function completed with success the
    ///   <c>Number</c> parameter contains a just created virtual COM port
    ///   number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   information about supported Bluetooth driver (API). </remarks>
    virtual int HalCreateComPort(const __int64 Address, const GUID& Service,
		unsigned short& Number) = 0;
    /// <summary> Destroys the virtual COM port. </summary>
    /// <param name="Number"> The virtual COM port number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   information about supported Bluetooth driver (API). </remarks>
    virtual int HalDestroyComPort(const unsigned short Number) = 0;
	/// <summary> Enumerates already installed Bluetooth virtual COM
    ///   ports. </summary>
    /// <param name="ComPorts"> If the function completed with success contains
    ///   array of all installed Bluetooth virtual COM ports. If not one vCOM
    ///   was found the value of the <c>ComPorts</c> parameter can be
    ///   <c>NULL</c>. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> The function enumerates all installed Bluetooth virtual
    ///   COM ports. The list includes vCOMs created by the application and
    ///   vCOMs created by an user outside the application. </para>
    ///   <para> A derived class must override this method to provide
    ///   information about supported Bluetooth driver (API). </para> </remarks>
	/// <seealso cref="wclVirtualComPorts" />
    virtual int HalEnumComPorts(wclVirtualComPorts& ComPorts) = 0;

	/* Remote Bluetooth device drivers management. */
	
	/// <summary> Enumerates services installed for specified Bluetooth
    ///   device. </summary>
    /// <param name="Address"> Remote device address. </param>
    /// <param name="Services"> If the method completed with success on output
    ///   contains GUID array of the installed services. If there is no services
    ///   installed for the specified device the <c>Services</c> parameter is
    ///   an empty array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   hardware dependent code that enumerates installed services. </remarks>
    /// <seealso cref="wclBluetoothInstalledServices" />
	virtual int HalEnumInstalledServices(const __int64 Address,
		wclBluetoothInstalledServices& Services) = 0;
	/// <summary> Install drivers for specified Bluetooth device. </summary>
	/// <param name="Address"> Remote device address. </param>
	/// <param name="Service"> A service's UUID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   hardware dependent code that installs driver. </remarks>
	virtual int HalInstallDevice(const __int64 Address, const GUID& Service) = 0;
	/// <summary> Uninstall drivers for specified Bluetooth device. </summary>
	/// <param name="Address"> Remote device address. </param>
	/// <param name="Service"> A service's UUID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   hardware dependent code that uninstalls driver. </remarks>
	virtual int HalUninstallDevice(const __int64 Address, const GUID& Service) = 0;

	/* HAL property getters. */
	
	/// <summary> Returns a Bluetooth API supported by the Radio
	///   object. </summary>
	/// <returns> The <see cref="wclBluetoothApi" /> describes a Bluetooth
	///   driver supported by this object. </returns>
	/// <remarks> A derived class must override this method to provide
	///   information about supported Bluetooth driver (API). </remarks>
	/// <seealso cref="wclBluetoothApi" />
	virtual wclBluetoothApi HalGetApi() const = 0;
	/// <summary> Returns a supported Bluetooth API name. </summary>
	/// <returns> A name of the supported Bluetooth API. </returns>
	/// <remarks> A derived class must override this method to provide
	///   information about supported Bluetooth driver (API) name. </remarks>
	virtual tstring HalGetApiName() const = 0;
	/// <summary> Implements a hardware-dependent code to check a Bluetooth
	///   hardware state. </summary>
	/// <returns> Returns <c>True</c> if a Bluetooth hardware is available.
	///   <c>False</c> otherwise. </returns>
	/// <remarks> A derived class must override this method to provide
	///   information about supported Bluetooth driver. </remarks>
	virtual bool HalGetAvailable() const = 0;
	/// <summary> Implements a hardware-dependent code to check a Bluetooth
	///   hardware physical state. </summary>
	/// <returns> Returns <c>True</c> if a Bluetooth hardware is physically
	///   available. <c>False</c> otherwise. </returns>
	/// <remarks> A derived class must override this method to provide
	///   information about supported Bluetooth driver. </remarks>
	virtual bool HalGetPlugged() const = 0;
	
	/* Helper methods and properties. */
	
	/// <summary> The method checks that a Bluetooth driver and a hardware is
	///   available. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> Any call to this method must be protected by
	///   the local radio Critical Section. </remarks>
	int CheckAvailable() const;
	
	/// <summary> Gets the devices discovering modification flag. </summary>
	/// <returns> The <c>bool</c> value indicates if paired devices must be
    ///   returned as found during devices discovering even if they are not
    ///   available. <c>true</c> if paired devices must be returned.
    ///   <c>false</c> if only available devices must be returned. </returns>
	bool GetIncludePaired() const;
	/// <summary> Gets the devices discovering modification flag. </summary>
	/// <value> The <c>bool</c> value indicates if paired devices must be
	///   returned as found during devices discovering even if they are not
	///   available. <c>true</c> if paired devices must be returned.
    ///   <c>false</c> if only available devices must be returned. </value>
    __declspec(property(get = GetIncludePaired)) bool IncludePaired;

	/// <summary> Gets the discovering type flag. </summary>
	/// <returns> <c>True</c> if LE discovering is executing. <c>False</c> if
	///   classic discovering is executing. </returns>
	bool GetLeDiscovering() const;
	/// <summary> Gets the discovering type flag. </summary>
	/// <value> <c>True</c> if LE discovering is executing. <c>False</c> if
	///   classic discovering is executing. </value>
	__declspec(property(get = GetLeDiscovering)) bool LeDiscovering;

	/// <summary> Gets the message receiver object. </summary>
	/// <returns> A <see cref="CwclMessageReceiver" /> object used in
	///   radio. </returns>
	/// <remarks> For internal use only. </remarks>
	/// <seealso cref="CwclMessageReceiver" />
    CwclMessageReceiver* GetReceiver() const;
	/// <summary> Gets the message receiver object. </summary>
	/// <value> A <see cref="CwclMessageReceiver" /> object used in
	///   radio. </value>
	/// <remarks> For internal use only. </remarks>
	/// <seealso cref="CwclMessageReceiver" />
    __declspec(property(get = GetReceiver)) CwclMessageReceiver* Receiver;

	/// <summary> Gets the pairing device address for manual pairing. </summary>
	/// <returns> A pairing device address. </returns>
	/// <remarks> For internal use only. </remarks>
	__int64 GetPairAddress() const;
	/// <summary> Gets the pairing device address for manual pairing. </summary>
	/// <value> A pairing device address. </value>
	/// <remarks> For internal use only. </remarks>
	__declspec(property(get = GetPairAddress)) __int64 PairAddress;

public:
	/// <summary> Creates a new radio object. </summary>
	/// <param name="Manager"> The <see cref="CwclBluetoothManager" /> object
	///   that creates and owns the Radio. If the <c>Manager</c> parameter is
	///   <c>NULL</c> the <see cref="wclECritical" /> exception raises. </param>
	/// <remarks> An application must never create the Radio objects directly.
	///   Instead of that an application must use methods of the
	///   <c>CwclBluetoothManager</c> component. </remarks>
	/// <seealso cref="CwclBluetoothManager" />
	/// <exception cref="wclECritical"></exception>
	CwclBluetoothRadio(CwclBluetoothManager* const Manager);
	/// <summary> Frees the Radio object. </summary>
	/// <remarks> An application must never destroy a Radio object directly.
	///   Instead of that an application must use methods of the
	///   <c>CwclBluetoothManager</c> component. </remarks>
	virtual ~CwclBluetoothRadio();

	/* Local radio methods. */
	
	/// <summary> Reads the local Bluetooth Radio MAC address. </summary>
	/// <param name="Address"> On output the local Bluetooth Radio
	///   address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetAddress(__int64& Address);
	/// <summary> Reads the local Bluetooth Radio Class Of Device
	///   (COD). </summary>
	/// <param name="Cod"> On output the local Bluetooth Radio COD. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetCod(unsigned long& Cod);
	/// <summary> Read the local Bluetooth Radio connectable state. </summary>
	/// <param name="Connectable"> On output the local Bluetooth Radio
	///   connectable state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> If the returned <c>Connectable</c> parameter value
	///   is <c>True</c> remote Bluetooth enabled devices can connect to
	///   this Radio. </para>
	///   <para> If the value of the <c>Connectable</c> parameter is
	///   <c>False</c> remote Bluetooth enabled devices can not connect to the
	///   Radio. </para> </remarks>
	int GetConnectable(bool& Connectable);
	/// <summary> Read the local Bluetooth Radio discoverable state. </summary>
	/// <param name="Discoverable"> On output the local Bluetooth Radio
	///   discoverable state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> If the returned <c>Discoverable</c> parameter value
	///   is <c>True</c> remote Bluetooth enabled devices can discover this
	///   Radio. </para>
	///   <para> If the value of the <c>Discoverable</c> parameter is
	///   <c>False</c> remote Bluetooth enabled devices can not discover the
	///   Radio. </para> </remarks>
	int GetDiscoverable(bool& Discoverable);
    /// <summary> Reads the HCI version of the local Radio module. </summary>
    /// <param name="Version"> On output the HCI version number. </param>
    /// <param name="Revision"> On output the HCI revision number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> The HCI version assignment numbers: </para>
    ///           <para> 0 - Bluetooth Core Specification 1.0b </para>
    ///           <para> 1 - Bluetooth Core Specification 1.1 </para>
    ///           <para> 2 - Bluetooth Core Specification 1.2 </para>
    ///           <para> 3 - Bluetooth Core Specification 2.0 + EDR </para>
    ///           <para> 4 - Bluetooth Core Specification 2.1 + EDR </para>
    ///           <para> 5 - Bluetooth Core Specification 3.0 + HS </para>
    ///           <para> 6 - Bluetooth Core Specification 4.0 </para>
    ///           <para> 7 - Bluetooth Core Specification 4.1 </para>
    ///           <para> 8 - Bluetooth Core Specification 4.2 </para>
	///           <para> 9 - Bluetooth Core Specification 5.0 </para>
	///           <para> 10 - Bluetooth Core Specification 5.1 </para>
	///           <para> 11 - Bluetooth Core Specification 5.2 </para>
	///           <para> 12-255 - Reserved </para> </remarks>
    int GetHciVersion(unsigned char& Version, unsigned short& Revision);
    /// <summary> Reads the LMP version of the local Radio module. </summary>
    /// <param name="Version"> On output the LMP version number. </param>
    /// <param name="Subversion"> On output the LMP subversion number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> The LMP version assignment numbers: </para>
    ///           <para> 0 - Bluetooth Core Specification 1.0b </para>
    ///           <para> 1 - Bluetooth Core Specification 1.1 </para>
    ///           <para> 2 - Bluetooth Core Specification 1.2 </para>
    ///           <para> 3 - Bluetooth Core Specification 2.0 + EDR </para>
    ///           <para> 4 - Bluetooth Core Specification 2.1 + EDR </para>
    ///           <para> 5 - Bluetooth Core Specification 3.0 + HS </para>
    ///           <para> 6 - Bluetooth Core Specification 4.0 </para>
    ///           <para> 7 - Bluetooth Core Specification 4.1 </para>
    ///           <para> 8 - Bluetooth Core Specification 4.2 </para>
	///           <para> 9 - Bluetooth Core Specification 5.0 </para>
	///           <para> 10 - Bluetooth Core Specification 5.1 </para>
	///           <para> 11 - Bluetooth Core Specification 5.2 </para>
	///           <para> 12–255 - Reserved </para> </remarks>
    int GetLmpVersion(unsigned char& Version, unsigned short& Subversion);
    /// <summary> Reads the Bluetooth Radio manufacturer ID. </summary>
    /// <param name="Manu"> On output the manufacturer ID. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The full list of the manufacturers ID can be found on the
    ///   Bluetooth SIG website by this link
    ///   https://www.bluetooth.com/specifications/assigned-numbers/company-Identifiers </remarks>
    int GetManufacturer(unsigned short& Manu);
    /// <summary> Reads the local Radio name. </summary>
    /// <param name="Name"> On output the local Bluetooth Radio
    ///   name. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetName(tstring& Name);

	/// <summary> Changes the local Bluetooth Radio Class Of Device
	///   (COD). </summary>
	/// <param name="Cod"> The new local Bluetooth Radio COD. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetCod(const unsigned long Cod);
	/// <summary> Changes the connectable state of the local Bluetooth
    ///   Radio. </summary>
    /// <param name="Connectable"> The new connectable state for the
    ///   Radio. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> Setting the <c>Conenctable</c> parameter to <c>True</c>
    ///   allows remote Bluetooth enabled devices to connect to this
    ///   Radio. </para>
    ///   <para> Setting the <c>Conenctable</c> parameter to <c>False</c>
    ///   blocks the Radio from remote Bluetooth enabled devices
    ///   connecting. </para>
    ///   <para> <c>Microsoft</c>: A radio that is non-connectable is
    ///   non-discoverable. The radio must be made non-discoverable prior to
    ///   making a radio non-connectable. Failure to make a radio
    ///   non-discoverable prior to making it non-connectable will result in
    ///   failure of this method call. </para> </remarks>
    int SetConnectable(const bool Connectable);
    /// <summary> Changes the discoverable state of the local Bluetooth
    ///   Radio. </summary>
    /// <param name="Discoverable"> The new discoverable state for the
    ///   Radio. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> Setting the <c>Discoverable</c> parameter to
    ///   <c>True</c> allows remote Bluetooth enabled devices to discover this
    ///   Radio. </para>
    ///   <para> Setting the <c>Discoverable</c> parameter to <c>False</c>
    ///   blocks the Radio from discovering by remote Bluetooth enabled
    ///   devices. </para>
    ///   <para> <c>Microsoft</c>: Use the <c>GetDiscoverable</c> method to
    ///   determine the current state of a Bluetooth radio. Windows ensures that
    ///   a discoverable system is connectable, and as such, the radio must
    ///   allow incoming connections prior to making a radio discoverable.
    ///   Failure to allow incoming connections results in the
    ///   <c>SetDiscoverable</c> method call failing. </para>
    ///   <para> When <c>SetDiscoverable</c> changes the discovery state, the
    ///   new state is valid for the lifetime of the calling application.
    ///   Additionally, if a Bluetooth radio previously made discoverable with
    ///   this function is disabled and re-enabled via the application,
    ///   discoverability will not persist. Once the calling application
    ///   terminates, the discovery state of the specified Bluetooth radio
    ///   reverts to the state it was in before <c>SetDiscoverable</c> was
    ///   called. </para> </remarks>
    int SetDiscoverable(const bool Discoverable);
    /// <summary> Sets a new name for the local Bluetooth Radio
    ///   module. </summary>
    /// <param name="Name"> The new Radio name. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int SetName(const tstring& Name);

	/// <summary> The method turns the local Bluetooth radio ON. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int TurnOn();
    /// <summary> The method turns the local Bluetooth radio OFF. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int TurnOff();

	/* Remote devices discovering. */

    /// <summary> Starts discovering for a remote Bluetooth enabled
    ///   devices. </summary>
    /// <param name="Timeout"> Specifies the maximum amount of time before
    ///   the inquiry is halted (in seconds). </param>
	/// <param name="Kind"> Specifies the discovered Bluetooth device
    ///   types. </param>
	/// <param name="IncludePaired"> Set this parameter to <c>true</c> if you
	///   need to get paired devices reported as just found even such devices
	///   are not available. If this parameter is <c>false</c> only available
	///   devices will be returned. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> If the discovering started the
    ///   <c>OnDiscoveringStarted</c> event of the
    ///   <see cref="CwclBluetoothManager" /> component fires. </para>
    ///   <para> When the discovering for the remote Bluetooth enabled devices
    ///   completed (with or without success) the <c>OnDiscoveringCompleted</c>
    ///   event of the <see cref="CwclBluetoothManager" /> component
    ///   fires. </para> </remarks>
	/// <seealso cref="wclBluetoothDiscoverKind" />
    int Discover(const unsigned char Timeout, const wclBluetoothDiscoverKind Kind,
		const bool IncludePaired = false);
    /// <summary> Terminates the discovering of remote Bluetooth enabled
    ///   devices. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <remarks> On legacy Windows (Windows XP, Vista, 7, 8 and 8.1) platforms
	///   with Microsoft Bluetooth drivers the Terminate method does not
	///   terminate discovering but simple indicates that the discovering result
	///   should be ignored and keeps discovering thread runs in background.
	///   If you call the <c>Close</c> method right after Terminate call and
	///   the discovering has not been completed yet you may get delay with the
	///   <c>Close</c> method return because it has to wait for the discovering
	///   thread completion. </remarks>
	int Terminate();
	
	/// <summary> The method enumerates already paired devices. </summary>
    /// <param name="Devices"> On output the dynamic array will be filled with
    ///   pared devices MACs. A caller is responsible to free the memory
    ///   allocated (if was) for this parameter. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int EnumPairedDevices(wclBluetoothAddresses& Devices);
	/// <summary> The method enumerates already paired devices. </summary>
	/// <param name="Kind"> Enumeration method: LE or Classic. </param>
	/// <param name="Devices"> On output the dynamic array will be filled with
	///   pared devices MACs. A caller is responsible to free the memory
	///   allocated (if was) for this parameter. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothDiscoverKind" />
    int EnumPairedDevices(const wclBluetoothDiscoverKind Kind,
		wclBluetoothAddresses& Devices);
	/// <summary> The method enumerates connected devices. </summary>
	/// <param name="Devices"> On output the dynamic array will be filled with
	///   connected devices MACs. A caller is responsible to free the memory
	///   allocated (if was) for this parameter. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int EnumConnectedDevices(wclBluetoothAddresses& Devices);

	/// <summary> Reads the available services from a remote Bluetooth
    ///   device. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="Uuid"> The pointer to a service's UUID. If an application
    ///   need to get information about specific service it set this
    ///   parameter to a valid pointer to the required service's UUID.
    ///   If this parameter is <c>NULL</c> the information about all available
    ///   services will be returned. </param>
    /// <param name="Services"> On output the remote Bluetooth device
    ///   services list. An application is responsible to free a memory
    ///   allocated for the array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int EnumRemoteServices(const __int64 Address, const GUID* const Uuid,
		wclBluetoothServices& Services);

	/// <summary> Checks if a remote device is in range. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC
	///   address. </param>
	/// <param name="InRange"> If the function completed with success
	///   indicates if a remote device is in range. <c>True</c> if a remote
	///   device is in range. <c>False</c> otherwise. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This function supports Classic Bluetooth devices
	///   only. </remarks>
	int IsRemoteDeviceInRange(const __int64 Address, bool& InRange);

	/// <summary> Forces a remote device disconnection. </summary>
	/// <param name="Address"> The remote Bluetooth device's MAC address. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This method can be used to disconnect a remote Bluetooth
	///   enabled device with the given MAC address. It can disconnect any
	///   Bluetooth enabled device even a connection was made by the system and
	///   outside Bluetooth Framework. </remarks>
	int RemoteDisconnect(const __int64 Address);

	/* Remote device functions. */

	/// <summary> Reads a remote device address type. </summary>
	/// <param name="Address"> A remote Bluetooth enabled device's MAC
	///   address. </param>
	/// <param name="AddrType"> On output a remote device's Address
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothAddressType" />
	int GetRemoteAddressType(const __int64 Address, wclBluetoothAddressType& AddrType);
    /// <summary> Reads a remote device COD (Class Of Device). </summary>
    /// <param name="Address"> A remote Bluetooth enabled device's MAC
    ///   address. </param>
    /// <param name="Cod"> On output a remote device's COD. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetRemoteCod(const __int64 Address, unsigned long& Cod);
    /// <summary> Read a remote Bluetooth device type. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="DevType"> On output a remote Bluetooth device
    ///   type. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclBluetoothDeviceType" />
    int GetRemoteDeviceType(const __int64 Address, wclBluetoothDeviceType& DevType);
    /// <summary> Queries a remote device's name. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="Name"> On output a remote device's name. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetRemoteName(const __int64 Address, tstring& Name);
    /// <summary> Reads a remote Bluetooth device paired status. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="Paired"> On output a remote Bluetooth device paired status.
    ///   if <c>True</c> a remote device has been paired with this
    ///   Radio. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetRemotePaired(const __int64 Address, bool& Paired);

	/// <summary> The function checks if the specified remote device is
    ///   currently connected. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="Connected"> On output the connected status of the
    ///   remote device. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetRemoteConnectedStatus(const __int64 Address, bool& Connected);
    /// <summary> Reads RSSI value from a remote device. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
    /// <param name="Rssi"> On output contains the RSSI value in dBm. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> Some devices require active connection to measure RSSI. If the method
	///   returns error an application can try to enumerate a device's services
	///   and immediately after that query RSSI once again. </remarks>
    int GetRemoteRssi(const __int64 Address, char& Rssi);

	/* Authentication. */

    /// <summary> Starts pairing with a remote Bluetooth device. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
	/// <param name="Method"> The pairing method. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothPairingMethod" />
	int RemotePair(const __int64 Address,
		const wclBluetoothPairingMethod Method = pmAuto);
	/// <summary> Unpair a remote Bluetooth device. </summary>
    /// <param name="Address"> The remote Bluetooth device's MAC
    ///   address. </param>
	/// <param name="Method"> The unpairing method. </param>
	/// <param name="Force"> Set this parameter to <c>true</c> to disable device
    ///   pairing state and force unpairing. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothPairingMethod" />
    int RemoteUnpair(const __int64 Address,
		const wclBluetoothPairingMethod Method = pmAuto,
		const bool Force = false);

	/* Secure Simple Pairing management. */
	
	/// <summary> Gets the radio Secure Simple Pairing mode. </summary>
	/// <param name="Enabled"> If the function completed with success on output
	///   contains a boolean that indicates the current Secure Simple Pairing
	///   (SSP) mode. <c>True</c> if SSP is enabled. <c>False</c> if SSP is
	///   disabled. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetSimplePairingMode(bool& Enabled);
	/// <summary> Sets the radio Secure Simple Pairing mode. </summary>
	/// <param name="Enable"> A boolean that indicates the new Secure Simple
	///   Pairing (SSP) mode. Set this parameter to <c>True</c> to enable SSP.
	///   Set this parameter to <c>False</c> to disable SSP. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetSimplePairingMode(const bool Enable);

	/* Virtual COM ports management. */

    /// <summary> Creates new virtual COM port. </summary>
    /// <param name="Address"> Remote device address. </param>
    /// <param name="Service"> A service's UUID. </param>
    /// <param name="Number"> If function completed with success the
    ///   <c>Number</c> parameter contains a just created virtual COM port
    ///   number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> A created vCOM is valid only while radio object is
    ///   available. </para>
    ///   <para> The <c>Service</c> parameter can be Serial Port Profile or
    ///   DialUp Networking Profile UUID. </para> </remarks>
    int CreateComPort(const __int64 Address, const GUID& Service, unsigned short& Number);
    /// <summary> Destroys the virtual COM port. </summary>
    /// <param name="Number"> The virtual COM port number. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <remarks> The function can destroy a vCOM created by the application
    ///   only. It can not destroy the vCOM created outside the
    ///   application. </remarks>
    int DestroyComPort(const unsigned short Number);
	/// <summary> Enumerates already installed Bluetooth virtual COM
    ///   ports. </summary>
    /// <param name="ComPorts"> If the function completed with success contains
    ///   array of all installed Bluetooth virtual COM ports. If not one vCOM
    ///   was found the value of the <c>ComPorts</c> parameter can be
    ///   <c>NULL</c>. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The function enumerates all installed Bluetooth virtual COM
    ///   ports. The list includes vCOMs created by the application and vCOMs
    ///   created by an user outside the application. </remarks>
	/// <seealso cref="wclVirtualComPorts" />
    int EnumComPorts(wclVirtualComPorts& ComPorts);
	
	/* Remote Bluetooth device drivers management. */
	
	/// <summary> Enumerates services installed for specified Bluetooth
    ///   device. </summary>
    /// <param name="Address"> Remote device address. </param>
    /// <param name="Services"> If the method completed with success on output
    ///   contains GUID array of the installed services. If there is no services
    ///   installed for the specified device the <c>Services</c> parameter is
    ///   an empty array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclBluetoothInstalledServices" />
	int EnumInstalledServices(const __int64 Address, wclBluetoothInstalledServices& Services);
	/// <summary> Install drivers for specified Bluetooth device. </summary>
	/// <param name="Address"> Remote device address. </param>
	/// <param name="Service"> A service's UUID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported with Microsoft Bluetooth
	///   drivers only. </remarks>
	int InstallDevice(const __int64 Address, const GUID& Service);
	/// <summary> Uninstall drivers for specified Bluetooth device. </summary>
	/// <param name="Address"> Remote device address. </param>
	/// <param name="Service"> A service's UUID. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported with Microsoft Bluetooth
	///   drivers only. </remarks>
	int UninstallDevice(const __int64 Address, const GUID& Service);
		
	/* Properties. */

    /// <summary> Gets a Bluetooth driver (API) supported by this Bluetooth
    ///   object. </summary>
    /// <returns> The Bluetooth API value. </returns>
    /// <seealso cref="wclBluetoothApi" />
	wclBluetoothApi GetApi() const;
	/// <summary> Gets a Bluetooth driver (API) supported by this Bluetooth
    ///   object. </summary>
    /// <value> The Bluetooth API value. </value>
    /// <seealso cref="wclBluetoothApi" />
	__declspec(property(get = GetApi)) wclBluetoothApi Api;
    
	/// <summary> Gets a supported Bluetooth API name. </summary>
    /// <returns> A string representation of the supported Bluetooth API. </returns>
    tstring GetApiName() const;
	/// <summary> Gets a supported Bluetooth API name. </summary>
    /// <value> A string representation of the supported Bluetooth API. </value>
	__declspec(property(get = GetApiName)) tstring ApiName;
    
	/// <summary> Gets a Radio hardware state. </summary>
    /// <returns> <c>True</c> if a Bluetooth hardware represented by this Radio
    ///   is available. <c>False</c> otherwise. </returns>
    bool GetAvailable() const;
	/// <summary> Gets a Radio hardware state. </summary>
    /// <value> <c>True</c> if a Bluetooth hardware represented by this Radio
    ///   is available. <c>False</c> otherwise. </value>
	__declspec(property(get = GetAvailable)) bool Available;

	/// <summary> Gets the Classic Bluetooth support status. </summary>
    /// <returns> Returns <c>true</c> if the Radio is available and supports
    ///   Classic Bluetooth. Returns <c>false</c> otherwise. </returns>
    /// <remarks> If the Radio supports Classic Bluetooth but is not available a
    ///   returning value is <c>false</c>. </remarks>
	bool GetClassicSupported() const;
	/// <summary> Gets the Classic Bluetooth support status. </summary>
    /// <value> Returns <c>true</c> if the Radio is available and supports
    ///   Classic Bluetooth. Returns <c>false</c> otherwise. </value>
    /// <remarks> If the Radio supports Classic Bluetooth but is not available a
    ///   returning value is <c>false</c>. </remarks>
	__declspec(property(get = GetClassicSupported)) bool ClassicSupported;
	
	/// <summary> Gets the array of the created virtual COM ports. </summary>
    /// <returns> The virtual COM ports array. </returns>
    /// <seealso cref="wclVirtualComPorts" />
    wclVirtualComPorts GetComPorts() const;
	/// <summary> Gets the array of the created virtual COM ports. </summary>
    /// <value> The virtual COM ports array. </value>
    /// <seealso cref="wclVirtualComPorts" />
	__declspec(property(get = GetComPorts)) wclVirtualComPorts ComPorts;
    
	/// <summary> Gets discovering state. </summary>
    /// <returns> <c>True</c> if discovering is executing on this Radio. </returns>
    bool GetDiscovering() const;
	/// <summary> Gets discovering state. </summary>
    /// <value> <c>True</c> if discovering is executing on this Radio. </value>
	__declspec(property(get = GetDiscovering)) bool Discovering;

	/// <summary> Gets the Bluetooth Low Energy support status. </summary>
    /// <returns> Returns <c>true</c> if the Radio is available and supports
    ///   Bluetooth Low Energy. Returns <c>false</c> otherwise. </returns>
    /// <remarks> If the Radio supports BLE but is not available a returning
    ///   value is <c>false</c>. </remarks>
	bool GetLeSupported() const;
	/// <summary> Gets the Bluetooth Low Energy support status. </summary>
    /// <value> Returns <c>true</c> if the Radio is available and supports
    ///   Bluetooth Low Energy. Returns <c>false</c> otherwise. </returns>
    /// <remarks> If the Radio supports BLE but is not available a returning
    ///   value is <c>false</c>. </value>
	__declspec(property(get = GetLeSupported)) bool LeSupported;
	
	/// <summary> Gets the <see cref="CwclBluetoothManager" /> object that owns
	///   the Radio. </summary>
	/// <returns> The <see cref="CwclBluetoothManager" /> object. </returns>
	/// <seealso cref="CwclBluetoothManager" />
	CwclBluetoothManager* GetManager() const;
	/// <summary> Gets the <see cref="CwclBluetoothManager" /> object that owns
	///   the Radio. </summary>
	/// <value> The <see cref="CwclBluetoothManager" /> object. </value>
	/// <seealso cref="CwclBluetoothManager" />
	__declspec(property(get = GetManager)) CwclBluetoothManager* Manager;
	
	/// <summary> Gets a manual pairing state. </summary>
    /// <returns> <c>True</c> if manual remote device pairing operation is
    ///   executing. <c>False</c> otherwise. </returns>
    bool GetPairing() const;
	/// <summary> Gets a manual pairing state. </summary>
    /// <value> <c>True</c> if manual remote device pairing operation is
    ///   executing. <c>False</c> otherwise. </value>
	__declspec(property(get = GetPairing)) bool Pairing;

	/// <summary> Gets a Radio hardware physical state. </summary>
	/// <returns> <c>True</c> if a Bluetooth hardware represented by this Radio
	///   is physically connected. <c>False</c> otherwise. </returns>
	bool GetPlugged() const;
	/// <summary> Gets a Radio hardware physical state. </summary>
	/// <value> <c>True</c> if a Bluetooth hardware represented by this Radio
	///   is physically connected. <c>False</c> otherwise. </value>
	__declspec(property(get = GetPlugged)) bool Plugged;
};

/// <summary> The Bluetooth Manager component. </summary>
/// <remarks> <para> The <c>CwclBluetoothManager</c> is the main component of
///   the Bluetooth Framework. Each application that uses the Bluetooth
///   Framework must have one and only one active instance of the
///   Bluetooth Manager. </para>
///   <para> This component must be created and opened in an application's
///   main thread only. </para> </remarks>
class CwclBluetoothManager
{
	DISABLE_COPY(CwclBluetoothManager);

private:
	friend class CwclBluetoothRadio;

	typedef std::list<CwclBluetoothRadio*>	RADIOS;

	bool					FActive;
	bool					FHandlePairing;
	RTL_CRITICAL_SECTION	FCS;
	HANDLE					FInstance;
	RADIOS*					FRadios;
	CwclMessageReceiver*	FReceiver;
	bool					FUseBled112;

	void MessageReceived(const CwclMessage* const Message);

	// Opens the radio and adds it into the radios list (if success).
    void AddRadio(CwclBluetoothRadio* const Radio);
	
protected:
	/// <summary> Fires the <c>AfterOpen</c> event. </summary>
    virtual void DoAfterOpen();
	/// <summary> Fires the <c>OnAuthenticationCompleted</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <param name="Error"> An operation result code. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoAuthenticationCompleted(CwclBluetoothRadio* const Radio,
		const __int64 Address, const int Error);
    /// <summary> Fires the <c>BeforeClose</c> event. </summary>
    virtual void DoBeforeClose();
	/// <summary> Fires the <c>OnClosed</c> event. </summary>
    virtual void DoClosed();
	/// <summary> Fires the <c>OnConfirm</c> event. </summary>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	virtual void DoConfirm(CwclBluetoothRadio* const Radio, const __int64 Address,
		bool& Confirm);
	/// <summary> Fires the <c>OnDeviceFound</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoDeviceFound(CwclBluetoothRadio* const Radio, const __int64 Address);
    /// <summary> Fires the <c>OnDiscoveringCompleted</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Error"> An operation result code. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoDiscoveringCompleted(CwclBluetoothRadio* const Radio, const int Error);
    /// <summary> Fires the <c>OnDiscoveringStarted</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoDiscoveringStarted(CwclBluetoothRadio* const Radio);
	/// <summary> Fires the <c>OnIoCapabilityRequest</c> event. </summary>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Mitm"> An application sets this parameter to specify the
	///   "Man in the Middle" protection required for authentication. </param>
	/// <param name="IoCapability"> An application sets this parameter to define
	///   the input/output capabilities of a Bluetooth Device. </param>
	/// <param name="OobPresent"> An application sets this parameter to
	///   <c>True</c> to force Out Of Band authentication. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothMitmProtection" />
	/// <seealso cref="wclBluetoothIoCapability" />
	virtual void DoIoCapabilityRequest(CwclBluetoothRadio* const Radio,
		const __int64 Address, wclBluetoothMitmProtection& Mitm,
		wclBluetoothIoCapability& IoCapability, bool& OobPresent);
	/// <summary> Fires the <c>OnNumericComparison</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <param name="Number"> A number sent by a remote device to display and
    ///   compare. </param>
    /// <param name="Confirm"> An application must set this parameter to
    ///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
    ///   pairing. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoNumericComparison(CwclBluetoothRadio* const Radio, const __int64 Address,
		const unsigned long Number, bool& Confirm);
	/// <summary> Fires the <c>OnOobDataRequest</c> event. </summary>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="OobData"> An application must set this parameter to
	///   the Out Of Band data received from peer device. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothOobData" />
	virtual void DoOobDataRequest(CwclBluetoothRadio* const Radio, const __int64 Address,
		wclBluetoothOobData& OobData);
	/// <summary> Fores the <c>OnPasskeyNotification</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <param name="Passkey"> A Passkey provided by a remote
    ///   Bluetooth device. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoPasskeyNotification(CwclBluetoothRadio* const Radio, const __int64 Address,
		const unsigned long Passkey);
    /// <summary> Fires the <c>OnPasskeyRequest</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <param name="Passkey"> A passkey provided by an application. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoPasskeyRequest(CwclBluetoothRadio* const Radio, const __int64 Address,
		unsigned long& Passkey);
    /// <summary> Fires the <c>OnPinRequest</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <param name="Address"> A remote device's MAC address. </param>
    /// <param name="Pin"> A PIN code provided by an application. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoPinRequest(CwclBluetoothRadio* const Radio, const __int64 Address,
		tstring& Pin);
	/// <summary> Fires the <c>OnProtectionLevelRequest</c> event. </summary>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Protection"> Describes the required protection
	///   level provided by an application. </param>
	/// <remarks> This method is used only during BLE pairing. </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothLeProtectionLevel" />
	virtual void DoProtectionLevelRequest(CwclBluetoothRadio* const Radio,
		const __int64 Address, wclBluetoothLeProtectionLevel& Protection);
	/// <summary> Fires the <c>OnStatusChanged</c> event. </summary>
    /// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
    ///   represents a Bluetooth driver that fired the event. </param>
    /// <seealso cref="CwclBluetoothRadio" />
    virtual void DoStatusChanged(CwclBluetoothRadio* const Radio);

public:
	/// <summary> Creates a new Bluetooth Manager component. </summary>
    /// <remarks> The component must always be created in an application's
    ///   main thread. </remarks>
	CwclBluetoothManager();
	/// <summary> Frees the component. </summary>
    /// <remarks> The component must always be destroyed in an application's
    ///   main thread. </remarks>
	virtual ~CwclBluetoothManager();

	/// <summary> Closes the Bluetooth Manager and releases all allocated
    ///   resources. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> After calling this method an application should not use
    ///   any of the Bluetooth Framework features. All instances of the
    ///   <see cref="CwclBluetoothRadio" /> class are not valid after
    ///   calling this method. </para>
    ///   <para> An application must call this method from its main thread
    ///   only. </para>
	///   <para> The call to this method may take some time because it requires
	///   to release all allocated resources and terminate all the running
	///   threads. The common case when the delay may appear is when your
	///   application started discovering for remote devices and right after
	///   that the Close was called. In this case Bluetooth Manager has to wait
	///   for discovering thread completion. </para> </remarks>
    int Close();
    /// <summary> Opens the Bluetooth Manager and allocated required
    ///   hardware resources. </summary>
	/// <param name="Apis"> The set of APIs the should be used by Bluetooth
	///   Framework. </param>
	/// <param name="HandlePairing"> Allows to disable pairing handling by
	///   Bluetooth Framework. Set this to <c>false</c> to disable Bluetooth
	///   Framework pairing. Set to <c>true</c> (the default value) to enable
	///   Bluetooth Framework pairing. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> An application must call this method before using any
    ///   of the Bluetooth Framework features. </para>
    ///   <para> An application must call this method from its main thread
    ///   only. </para> </remarks>
	/// <seealso cref="wclBluetoothApis" />
    int Open(const wclBluetoothApis Apis, const bool HandlePairing = true);
	/// <summary> Opens the Bluetooth Manager and allocated required
	///   hardware resources. </summary>
	/// <param name="HandlePairing"> Allows to disable pairing handling by
	///   Bluetooth Framework. Set this to <c>false</c> to disable Bluetooth
	///   Framework pairing. Set to <c>true</c> (the default value) to enable
	///   Bluetooth Framework pairing. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> An application must call this method before using any
	///   of the Bluetooth Framework features. </para>
	///   <para> An application must call this method from its main thread
	///   only. </para> </remarks>
	int Open(const bool HandlePairing = true);

	/// <summary> Gets the first available Radio object. </summary>
	/// <param name="Radio"> If the function completed with success on output
	///   contains the first found available Bluetooth Radio object. Otherwise
	///   the parameter contains <c>NULL</c>. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	int GetRadio(CwclBluetoothRadio*& Radio) const;
	/// <summary> Gets the first available Radio object that supports Bluetooth
	///   Low Energy features. </summary>
	/// <param name="Radio"> If the function completed with success on output
	///   contains the first found available Bluetooth Radio object. Otherwise
	///   the parameter contains <c>NULL</c>. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	int GetLeRadio(CwclBluetoothRadio*& Radio) const;
	/// <summary> Gets the first available Radio object that supports Classic
	///   Bluetooth features. </summary>
	/// <param name="Radio"> If the function completed with success on output
	///   contains the first found available Bluetooth Radio object. Otherwise
	///   the parameter contains <c>NULL</c>. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	int GetClassicRadio(CwclBluetoothRadio*& Radio) const;

	/// <summary> Gets the Bluetooth Manager state. </summary>
    /// <returns> <c>True</c> if the Bluetooth Manager is active
    ///   (opened). </returns>
    bool GetActive() const;
	/// <summary> Gets the Bluetooth Manager state. </summary>
    /// <value> <c>True</c> if the Bluetooth Manager is active
    ///   (opened). </value>
	__declspec(property(get = GetActive)) bool Active;

	/// <summary> Gets the number of available Bluetooth Radios. </summary>
    /// <returns> The number of available Bluetooth Radios. </returns>
    size_t GetCount() const;
	/// <summary> Gets the number of available Bluetooth Radios. </summary>
    /// <value> The number of available Bluetooth Radios. </value>
	__declspec(property(get = GetCount)) size_t Count;

	/// <summary> Gets the discovering state. </summary>
	/// <returns> <c>True</c> if at least one radio is in discovering state.
    ///   <c>False</c> otherwise. </returns>
    bool GetDiscovering();
	/// <summary> Gets the discovering state. </summary>
	/// <value> <c>True</c> if at least one radio is in discovering state.
	///   <c>False</c> otherwise. </value>
	__declspec(property(get = GetDiscovering)) bool Discovering;

	/// <summary> Gets the pairing handling flag. </summary>
	/// <returns> The pairing handling state. <c>True</c> if the pairing is
    ///   handled by Bluetooth Framework. <c>False</c> if the pairing is handled
    ///   by the system. </returns>
    /// <remarks> This flag doe snot affect <c>Bled112</c> USB dongle because
    ///   it does not have any support from the OS. </remarks>
    bool GetHandlePairing() const;
	/// <summary> Gets the pairing handling flag. </summary>
	/// <value> The pairing handling state. <c>True</c> if the pairing is
    ///   handled by Bluetooth Framework. <c>False</c> if the pairing is handled
    ///   by the system. </value>
    /// <remarks> This flag doe snot affect <c>Bled112</c> USB dongle because
    ///   it does not have any support from the OS. </remarks>
	__declspec(property(get = GetHandlePairing)) bool HandlePairing;

    /// <summary> Gets the Bluetooth Radio by its index. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object. </returns>
    CwclBluetoothRadio* GetRadios(const size_t Index) const;
	/// <summary> Gets the Bluetooth Radio by its index. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object. </value>
	__declspec(property(get = GetRadios)) CwclBluetoothRadio* Radios[];

	/// <summary> The event fires after the Bluetooth Manager has been
    ///   successfully opened. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(AfterOpen);
    /// <summary> The event fires before the Bluetooth Manager will be
    ///   closed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(BeforeClose);
    /// <summary> The event fires when authentication (pairing) with a remote
    ///   Bluetooth device has completed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Error"> An operation result code. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothDeviceResultEvent(OnAuthenticationCompleted);
	/// <summary> The event fires when a remote Bluetooth device requires
	///   a pairing confirmation. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothConfirmEvent(OnConfirm);
	/// <summary> The event fires when the Bluetooth Manager has completely
    ///   been closed. </summary>
    wclNotifyEvent(OnClosed);
	/// <summary> The event fires when a new remote Bluetooth device found
	///   during discovering. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothDeviceEvent(OnDeviceFound);
    /// <summary> The event fires when discovering for remote Bluetooth
    ///   devices has been completed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Error"> An operation result code. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothResultEvent(OnDiscoveringCompleted);
    /// <summary> The event fires when discovering for remote Bluetooth
    ///   devices has been started. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothEvent(OnDiscoveringStarted);
	/// <summary> The event fires when a remote device requests an IO capability
    ///   of the local Bluetooth device. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Mitm"> An application sets this parameter to specify the
	///   "Man in the Middle" protection required for authentication. </param>
	/// <param name="IoCapability"> An application sets this parameter to define
	///   the input/output capabilities of a Bluetooth Device. </param>
	/// <param name="OobPresent"> An application sets this parameter to
	///   <c>True</c> to force Out Of Band authentication. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothMitmProtection" />
	/// <seealso cref="wclBluetoothIoCapability" />
	wclBluetoothIoCapabilityRequestEvent(OnIoCapabilityRequest);
	/// <summary> The event fires when a remote Bluetooth device requires
    ///   a numeric comparison pairing. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Number"> A number sent by a remote device to display and
	///   compare. </param>
	/// <param name="Confirm"> An application must set this parameter to
	///   <c>True</c> to confirm pairing. Set it to <c>False</c> to reject
	///   pairing. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothNumericComparisonEvent(OnNumericComparison);
	/// <summary> The event fires when a remote device requests an Out Of Band
    ///   pairing data. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="OobData"> An application must set this parameter to
	///   the Out Of Band data received from peer device. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	wclBluetoothOobDataRequestEvent(OnOobDataRequest);
	/// <summary> The event fires when a remote Bluetooth device notifies
    ///   an application about its passkey. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Passkey"> A Passkey provided by a remote
	///   Bluetooth device. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothPasskeyNotificationEvent(OnPasskeyNotification);
    /// <summary> The event fires when a remote Bluetooth device requires
    ///   a passkey for pairing. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Passkey"> A Passkey provided by an application. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothPasskeyRequestEvent(OnPasskeyRequest);
    /// <summary> The event fires when a remote Bluetooth device requires
    ///   a legacy PIN pairing. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Pin"> A PIN code provided by an application. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothPinRequestEvent(OnPinRequest);
	/// <summary> The event fires during BLE pairing to request required
    ///   pairing protection level. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <param name="Address"> A remote device's MAC address. </param>
	/// <param name="Protection"> Describes the required protection
	///   level provided by an application. </param>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothLeProtectionLevel" />
    wclBluetoothProtectionLevelRequestEvent(OnProtectionLevelRequest);
	/// <summary> The event fires when a status of a Bluetooth hardware or
    ///   driver has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Radio"> A <see cref="CwclBluetoothRadio" /> object
	///   represents a Bluetooth driver that fired the event. </param>
	/// <seealso cref="CwclBluetoothRadio" />
    wclBluetoothEvent(OnStatusChanged);
};

/* Connections */

/// <summary> The base class for all Classic Bluetooth (RFCOMM) client
///   connections. </summary>
/// <remarks> An application must never create instances of this class
///   directly. Instead of that an application must use related methods
///   from the <see cref="CwclBluetoothRadio" /> object. </remarks>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="CwclClientDataConnection" />
class CwclRfCommClientConnection : public CwclClientDataConnection
{
	DISABLE_COPY(CwclRfCommClientConnection);

private:
	friend class CwclBluetoothRadio;

	// The radio that owns the connection.
    CwclBluetoothRadio*	FRadio;

    __int64				FAddress;
    bool				FAuthentication;
    unsigned char		FChannel;
    bool				FEncryption;
    GUID				FService;

protected:
	/// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

public:
	/// <summary> Create new Classic Bluetooth client connection. </summary>
    /// <param name="Radio"> The Radio object that owns the connection. </param>
    /// <remarks> <para> An application must never create this class directly.
    ///   Instead of that an application must use upper-level methods and
    ///   classes. </para>
    ///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
    ///   <see cref="wclECritical" /> exception raises. </para> </remarks>
    /// <seealso cref="CwclBluetoothRadio" />
    /// <exception cref="wclECritical"></exception>
	CwclRfCommClientConnection(CwclBluetoothRadio* const Radio);

	/// <summary> Connects to a remote device. </summary>
    /// <param name="Address"> The remote Bluetooth device address. </param>
    /// <param name="Service"> The Bluetooth Service UUID. If the <c>Channel</c>
    ///   parameter is zero, the system attempts to use <c>Service</c> to
    ///   resolve the remote channel corresponding to the service. The service
    ///   class is a normalized 128-bit GUID, defined by the Bluetooth
    ///   specification. Common GUIDs are defined by the Bluetooth Assigned
    ///   Numbers document. Alternatively, a unique GUID may be used for a
    ///   domain-specific application. </param>
    /// <param name="Channel"> The RFCOMM channel number. If zero the
    ///   <c>Service</c> UUID will be used. </param>
    /// <param name="Authentication"> Specifies that authentication is required
    ///   for a connect operation to complete successfully. Setting this option
    ///   actively initiates authentication during connection establishment,
    ///   if the two Bluetooth devices were not previously
    ///   authenticated. </param>
    /// <param name="Encryption"> The option enforces encryption to establish a
    ///   connection. Encryption is only available for authenticated
    ///   connections. </param>
    /// <param name="Timeout"> The connect timeout in milliseconds. The
    ///   default value is 10000 milliseconds. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> The method starts a connection operation to a remote
    ///   device. If the method success that does not mean that the connection
    ///   was established. That just means that the connection operation was
    ///   started. The real connection result will be passed to the
    ///   <c>OnConnect</c> event handler. </para>
    ///   <para> NOTE: BlueSoleil does not support <c>Authentication</c>
    ///   and <c>Encryption</c> parameters per connection. </para> </remarks>
    int Connect(const __int64 Address, const GUID& Service, const unsigned char Channel = 0,
		const bool Authentication = true, const bool Encryption = false,
		const unsigned long Timeout = 10000);

	/// <summary> Gets a remote device MAC address. </summary>
    /// <returns> The remote device MAC address. </returns>
    __int64 GetAddress() const;
	/// <summary> Gets a remote device MAC address. </summary>
    /// <value> The remote device MAC address. </value>
	__declspec(property(get = GetAddress)) __int64 Address;

    /// <summary> Gets the authentication value. </summary>
    /// <returns> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </returns>
    bool GetAuthentication() const;
	/// <summary> Gets the authentication value. </summary>
    /// <value> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </value>
	__declspec(property(get = GetAuthentication)) bool Authentication;

    /// <summary> Gets the target service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <returns> The RFCOMM channel number used for connection. </returns>
    unsigned char GetChannel() const;
	/// <summary> Gets the target service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <value> The RFCOMM channel number used for connection. </value>
	__declspec(property(get = GetChannel)) unsigned char Channel;

    /// <summary> Gets the encryption state of the connection. </summary>
    /// <returns> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </returns>
    bool GetEncryption() const;
	/// <summary> Gets the encryption state of the connection. </summary>
    /// <value> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </value>
	__declspec(property(get = GetEncryption)) bool Encryption;

    /// <summary> Gets the connection owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

    /// <summary> Gets the target Bluetooth service UUID used for
    ///   connection. </summary>
    /// <returns> A Bluetooth service UUID. </returns>
    GUID GetService() const;
	/// <summary> Gets the target Bluetooth service UUID used for
    ///   connection. </summary>
    /// <value> A Bluetooth service UUID. </value>
	__declspec(property(get = GetService)) GUID Service;
};

/// <summary> The Bluetooth RFCOMM server client connection base class. </summary>
/// <seealso cref="CwclServerDataConnection" />
class CwclRfCommServerClientConnection : public CwclServerClientDataConnection
{
	DISABLE_COPY(CwclRfCommServerClientConnection);

private:
    __int64	FAddress;

protected:
    /// <summary> Sets the connected device MAC address. </summary>
    /// <remarks> For internal use only. </remarks>
    void SetAddress(const __int64 Address);

public:
    /// <summary> Create the new RFCOMM server client connection. </summary>
    CwclRfCommServerClientConnection();

    /// <summary> Gets the connected remote device's address. </summary>
    /// <returns> The remote device's MAC address. </returns>
    __int64 GetAddress() const;
	/// <summary> Gets the connected remote device's address. </summary>
    /// <value> The remote device's MAC address. </value>
	__declspec(property(get = GetAddress)) __int64 Address;
};

/// <summary> The base class for all WCL Bluetooth RFCOMM based
///   server connections. </summary>
/// <remarks> An application must never create instances of this class
///   directly. Instead of that an application must use related methods
///   from the <see cref="CwclBluetoothRadio" /> object. </remarks>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="CwclServerDataConnection" />
class CwclRfCommServerConnection : public CwclServerDataConnection
{
	DISABLE_COPY(CwclRfCommServerConnection);

private:
	friend class CwclBluetoothRadio;

    // The radio that owns the connection.
    CwclBluetoothRadio*	FRadio;

    bool				FAuthentication;
    unsigned char		FAssignedChannel;
    unsigned char		FChannel;
    bool				FEncryption;
    GUID				FService;
    tstring				FServiceName;

protected:
    /// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

    /// <summary> Sets the assigned RFCOMM channel number. </summary>
    /// <remarks> For internal use only. </remarks>
    void SetAssignedChannel(const unsigned char Channel);

    /// <summary> Fires the <c>GetSdpAttributes</c> event. </summary>
    /// <param name="Protocols"> The additional protocol descriptors array that
    ///   should be added to SDP record. </param>
    /// <param name="Profiles"> The profile list that should be added to SDP
    ///   record. </param>
    /// <param name="Formats"> Other attributes that should be added to SDP
    ///   record. </param>
    /// <param name="Cod"> <para> Class of device (COD) information. A 32-bit
    ///   parameter of COD_SERVICE_* class of device bits associated with this
    ///   SDP record. The system combines these bits with COD bits from other
    ///   service records and system characteristics. The resulting class of
    ///   device for the local radio is advertised when the radio is found during
    ///   device inquiry. When the last SDP record associated with a particular
    ///   service bit is deleted, that service bit is no longer reported in
    ///   responses to future device inquiries. </para>
    ///   <para> The format and possible values for the COD field are defined in
    ///   the Bluetooth Assigned Numbers 1.1 portion of the Bluetooth
    ///   specification, Section 1.2. (This resource may not be available in some
    ///   languages and countries.) </para> </param>
    /// <remarks> <para> The HAL Radio implementation calls this method when
    ///   needs to add custom attributes into the SDP record. </para>
    ///   <para> BlueSoleil driver does not support custom SDP records and this
    ///   method does not work with BlueSoleil Bluetooth driver. </para>
    ///   <para> A derived class must always call the inherited
    ///   method.  </para> </remarks>
	/// <seealso cref="wclBluetoothSdpProtocols" />
    /// <seealso cref="wclBluetoothSdpProfiles" />
    /// <seealso cref="wclBluetoothSdpFormats" />
    virtual void DoGetSdpAttributes(wclBluetoothSdpProtocols& Protocols,
		wclBluetoothSdpProfiles& Profiles, wclBluetoothSdpFormats& Formats,
		unsigned long& Cod);

public:
    /// <summary> Create new Classic Bluetooth server connection. </summary>
    /// <param name="Radio"> The Radio object that owns the connection. </param>
    /// <remarks> <para> An application must never create this class directly.
    ///   Instead of that an application must use upper-level methods and
    ///   classes. </para>
    ///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
    ///   <see cref="wclECritical" /> exception raises. </para> </remarks>
    /// <seealso cref="CwclBluetoothRadio" />
    /// <exception cref="wclECritical"></exception>
    CwclRfCommServerConnection(CwclBluetoothRadio* const Radio);

    /// <summary> The method starts listening for client connections. </summary>
    /// <param name="Service"> The Bluetooth Service UUID. If the <c>Channel</c>
    ///   parameter is zero, the system attempts to use <c>Service</c> to
    ///   resolve the remote channel corresponding to the service. The service
    ///   class is a normalized 128-bit GUID, defined by the Bluetooth
    ///   specification. Common GUIDs are defined by the Bluetooth Assigned
    ///   Numbers document. Alternatively, a unique GUID may be used for a
    ///   domain-specific application. </param>
    /// <param name="ServiceName"> The option service name. </param>
    /// <param name="Channel"> The RFCOMM channel number. If zero the
    ///   <c>Service</c> UUID will be used. </param>
    /// <param name="Authentication"> Specifies that authentication is required
    ///   for a connect operation to complete successfully. Setting this option
    ///   actively initiates authentication during connection establishment,
    ///   if the two Bluetooth devices were not previously
    ///   authenticated. </param>
    /// <param name="Encryption"> The option enforces encryption to establish a
    ///   connection. Encryption is only available for authenticated
    ///   connections. </param>
     /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> NOTE: BlueSoleil has limited support for <c>Authentication</c>
    ///   and <c>Encryption.</c>. Also it doe snot support user-defined RFCOMM
    ///   channel number. </remarks>
	int Listen(const GUID& Service, const tstring& ServiceName = _T(""),
		const unsigned char Channel = 0, const bool Authentication = true,
		const bool Encryption = false);
	
	/// <summary> Gets the authentication value. </summary>
    /// <returns> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </returns>
    bool GetAuthentication() const;
	/// <summary> Gets the authentication value. </summary>
    /// <value> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </value>
	__declspec(property(get = GetAuthentication)) bool Authentication;

    /// <summary> Gets the assigned RFCOMM channel number. </summary>
    /// <returns> The RFCOMM channel number. </returns>
    unsigned char GetAssignedChannel() const;
	/// <summary> Gets the assigned RFCOMM channel number. </summary>
    /// <value> The RFCOMM channel number. </value>
	__declspec(property(get = GetAssignedChannel)) unsigned char AssignedChannel;

    /// <summary> Gets the service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <returns> The RFCOMM channel number used for connection. </returns>
    unsigned char GetChannel() const;
	/// <summary> Gets the service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <value> The RFCOMM channel number used for connection. </value>
	__declspec(property(get = GetChannel)) unsigned char Channel;

    /// <summary> Gets the encryption state of the connection. </summary>
    /// <returns> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </returns>
    bool GetEncryption() const;
	/// <summary> Gets the encryption state of the connection. </summary>
    /// <value> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </value>
	__declspec(property(get = GetEncryption)) bool Encryption;

    /// <summary> Gets the connection owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

    /// <summary> Gets the Bluetooth service UUID used for
    ///   connection. </summary>
    /// <returns> A Bluetooth service UUID. </returns>
    GUID GetService() const;
	/// <summary> Gets the Bluetooth service UUID used for
    ///   connection. </summary>
    /// <value> A Bluetooth service UUID. </value>
	__declspec(property(get = GetService)) GUID Service;

    /// <summary> Gets the service name. </summary>
    /// <returns> The service name. </returns>
    tstring GetServiceName() const;
	/// <summary> Gets the service name. </summary>
    /// <value> The service name. </value>
	__declspec(property(get = GetServiceName)) tstring ServiceName;

    /// <summary> The event fires when the server builds SDP record for
    ///   the service it runs. If an application needs to provide
    ///   additional attributes it should handle the event. By default no
    ///   additional attributes is added for the SDP record. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Protocols"> The additional protocol descriptors array that
	///   should be added to SDP record. </param>
	/// <param name="Profiles"> The profile descriptors list that should be added
	///   to SDP record. </param>
	/// <param name="Formats"> Other attributes that should be added to SDP
	///   record. </param>
	/// <param name="Cod"> <para> Class of device (COD) information. A 32-bit
	///   parameter of COD_SERVICE_* class of device bits associated with this
	///   SDP record. The system combines these bits with COD bits from other
	///   service records and system characteristics. The resulting class of
	///   device for the local radio is advertised when the radio is found during
	///   device inquiry. When the last SDP record associated with a particular
	///   service bit is deleted, that service bit is no longer reported in
	///   responses to future device inquiries. </para>
	///   <para> The format and possible values for the COD value are defined in
	///   the Bluetooth Assigned Numbers 1.1 portion of the Bluetooth
	///   specification, Section 1.2. (This resource may not be available in some
	///   languages and countries.) </para> </param>
	/// <seealso cref="wclBluetoothSdpProtocols" />
	/// <seealso cref="wclBluetoothSdpProfiles" />
	/// <seealso cref="wclBluetoothSdpFormats" />
    wclBluetoothGetSdpAttributesEvent(GetSdpAttributes);
};

/// <summary> The class represents a Bluetooth LE GATT client
///   connection. </summary>
/// <remarks> An application must never create instances of this class
///   directly. Instead of that an application must use related methods
///   from the <see cref="CwclBluetoothRadio" /> object. </remarks>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="CwclClientConnection" />
class CwclGattClientConnection : public CwclClientConnection
{
	DISABLE_COPY(CwclGattClientConnection);

private:
	friend class CwclBluetoothRadio;

	typedef std::list<void*> VOID_LIST;

    __int64				FAddress; // Remote device address.
	bool				FConnectOnRead; // Connection flag.
	bool				FForceNotifications;
	CwclBluetoothRadio*	FRadio; // The owner.
	bool				FRemoteDisconnected;
	VOID_LIST*			FSubscriptions; // Subscriptions.
	VOID_LIST*			FSubscribedDescriptors;

	/* Message processing. */

    void ProcessCharacteristicChangeMessage(const unsigned short Handle,
		void* const Value, const unsigned long Size);

protected:
	/// <summary> The method called internally before connection. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class may override this method to process some
	///   connection pre-requirements that should be executed in the main
	///   thread UI. Used by BLED112 to be able to get protection
	///   parameters. </remarks>
    virtual int PrepareForConnection();

    /// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

    /// <summary> Implements a hardware-dependent code that connects to a
    ///   remote device. </summary>
    /// <param name="Event"> The system even object handle. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> Derived classes must override this method to implement
    ///   a hardware-dependent code that connects to a remote device. </para>
    ///   <para> The method executes in a separate thread. </para>
    ///   <para> The method implementation must monitor the <c>Event</c>
    ///   parameter. The <c>Event</c> parameter is set if the
    ///   <c>Disconnect</c> method was called. If the termination event was set
    ///   the method must terminate connection operation. </para>
    ///   <para> If connection to a remote device was terminated the method
    ///   must release all allocated resources because the <c>HalDisconnect</c>
    ///   will not be called. </para>
    ///   <para> A derived class must always call inherited
    ///   method. </para> </remarks>
    virtual int HalConnect(const HANDLE Event) override;
    /// <summary> Implements a hardware-dependent code that disconnects from the
    ///   connected remote device. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> The method is called only if a connection to a remote
    ///   device was established with success (the <c>Connect</c> method was
    ///   success). </para>
    ///   <para> The method will not be called if the connection to the  remote
    ///   device was terminated in the middle of the <c>HalConnect</c>
    ///   method. </para>
    ///   <para> A derived class must always call inherited
    ///   method. </para> </remarks>
    virtual int HalDisconnect() override;

    /// <summary> Fires the <c>OnCharacteristicChanged</c> event. </summary>
    /// <param name="Handle"> A changed characteristic handle. </param>
    /// <param name="Value"> A pointer to the characteristic value. </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
    /// <remarks> The <c>Value</c> parameter is valid only inside the event
    ///   handler. If an application needs to use it outside the event handler
    ///   it must be copied. </remarks>
    virtual void DoCharacteristicChanged(const unsigned short Handle,
		const unsigned char* const Value, const unsigned long Length);
	/// <summary> Fires the <c>OnConnectionParamsChanged</c> event. </summary>
	virtual void DoConnectionParamsChanged();
	/// <summary> Fires the <c>OnConnectionPhyChanged</c> event. </summary>
    virtual void DoConnectionPhyChanged();
	/// <summary> Fires the <c>OnPduMaxSizeChanged</c> event. </summary>
    virtual void DoMaxPduSizeChanged();

    /* HAL GATT methods. */

    /// <summary> Implements a hardware-dependent code for reading the
    ///   characteristics available for the specified service. </summary>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Characteristics"> On output a list of the service's
    ///   characteristics. An application is responsible to clean up a memory
    ///   allocated for the dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattCharacteristics" />
    virtual int HalReadCharacteristics(const wclGattService& Service, const wclGattOperationFlag Flag,
		wclGattCharacteristics& Characteristics) = 0;
    /// <summary> Implements a hardware-dependent code for reading the value of
    ///   the specified characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> On output contains a pointer to the characteristic's value.
    ///   An application is responsible to clean up a memory allocated for the value. </param>
	/// <param name="Length"> On output contains a characteristic value length in
	///   bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
    virtual int HalReadCharacteristicValue(const wclGattCharacteristic& Characteristic,
		const wclGattOperationFlag Flag, const wclGattProtectionLevel Protection,
		unsigned char*& Value, unsigned long& Length) = 0;
    /// <summary> The method reads all the descriptors available for the
    ///   specified characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Descriptors"> On output contains the list of the
    ///   characteristic's descriptors. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattDescriptors" />
    virtual int HalReadDescriptors(const wclGattCharacteristic& Characteristic,
		const wclGattOperationFlag Flag, wclGattDescriptors& Descriptors) = 0;
    /// <summary> Implements a hardware-dependent code for reading the value of
    ///   the specified descriptor. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A descriptor's value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattDescriptor" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
    /// <seealso cref="wclGattDescriptorValue" />
    virtual int HalReadDescriptorValue(const wclGattDescriptor& Descriptor,
		const wclGattOperationFlag Flag, const wclGattProtectionLevel Protection,
		wclGattDescriptorValue& Value) = 0;
    /// <summary> Implements a hardware-dependent code for reading the included
    ///   services available for a given service. </summary>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    virtual int HalReadIncludedServices(const wclGattService& Service,
		const wclGattOperationFlag Flag, wclGattServices& Services) = 0;
    /// <summary> Implements a hardware-dependent code for reading available
    ///   services from a remote Bluetooth LE device. </summary>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    virtual int HalReadServices(const wclGattOperationFlag Flag,
		wclGattServices& Services) = 0;

	/// <summary> Implements a hardware-dependent code to write the specified
    ///   characteristic value to the Bluetooth device. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A pointer to the characteristic's value data. </param>
	/// <param name="Length"> A characteristic value length in bytes. </value>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
	/// <seealso cref="wclGattProtectionLevel" />
    virtual int HalWriteCharacteristicValue(const wclGattCharacteristic& Characteristic,
		const wclGattProtectionLevel Protection, const unsigned char* const Value,
		const unsigned long Length) = 0;
    /// <summary> Implements a hardware-dependent code to write the specified
    ///   descriptor value to the Bluetooth device. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A descriptor's value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattDescriptor" />
	/// <seealso cref="wclGattProtectionLevel" />
    /// <seealso cref="wclGattDescriptorValue" />
	virtual int HalWriteDescriptorValue(const wclGattDescriptor& Descriptor,
		const wclGattProtectionLevel Protection, const wclGattDescriptorValue& Value) = 0;

	/* HAL characteristics changes notifications. */

    /// <summary> Implements a hardware-dependent code to subscribes for the
	///   characteristic changes notifications. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is interested. </param>
    /// <param name="Hdl"> On output the subscription handle. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
    virtual int HalSubscribe(const wclGattCharacteristic& Characteristic, HANDLE& Hdl) = 0;
    /// <summary> Implements a hardware-dependent code to unsubscribes from the
	///   characteristic changes notifications. </summary>
    /// <param name="Hdl"> The subscription handle. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    virtual int HalUnsubscribe(const HANDLE Hdl) = 0;

	/* Connection parameters. */
	
	/// <summary> Implements a hardware-dependent code to get the current
	///   connection parameters. </summary>
	/// <param name="Params"> If the function completed with success on output
	///   contains the current connection parameters. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParameters" />
	virtual int HalGetConnectionParams(wclBluetoothLeConnectionParameters& Params) = 0;
	/// <summary> Implements a hardware-dependent code to request the connection
	///   parameters change to the specified preferred connection
	///   parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersType" />
	virtual int HalSetConnectionParams(
		const wclBluetoothLeConnectionParametersType Params) = 0;
	/// <summary> Implements a hardware-dependent code to request the connection
	///   parameters change to the specified preferred connection
	///   parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   value. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersValue" />
	virtual int HalSetConnectionParams(
		const wclBluetoothLeConnectionParametersValue& Params) = 0;

	/// <summary> Implements a hardware-dependent code to reads the maximum PDU
	///   size for the current connection. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum PDU size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalGetMaxPduSize(unsigned short& Size) = 0;

	/// <summary> Implements a hardware-dependent code to reads the Bluetooth LE
	///   physical layer (PHY) information. </summary>
	/// <param name="Info"> If the method completed with success on output
	///   contains the connection PHY information. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionPhy" />
    virtual int HalGetConnectionPhyInfo(wclBluetoothLeConnectionPhy& Info) = 0;

public:
    /// <summary> Creates a new GATT client connection object. </summary>
    /// <param name="Radio"> The Radio object that owns the connection. </param>
    /// <remarks> <para> An application must never create this class directly.
    ///   Instead of that an application must use upper-level methods and
    ///   classes. </para>
    ///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
    ///   <see cref="wclECritical" /> exception raises. </para> </remarks>
    /// <seealso cref="CwclBluetoothRadio" />
    /// <exception cref="wclECritical"></exception>
    CwclGattClientConnection(CwclBluetoothRadio* const Radio);

	/// <summary> The method reads all the characteristics available for the
    ///   specified service. </summary>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Characteristics"> On output a list of the service's
    ///   characteristics. An application is responsible to clean up a memory
    ///   allocated for the dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattCharacteristics" />
    int ReadCharacteristics(const wclGattService& Service, const wclGattOperationFlag Flag,
		wclGattCharacteristics& Characteristics);
    /// <summary> The method reads the value of the specified
    ///   characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> On output contains a pointer to the characteristic's value.
	///   An application is responsible to clean up a memory allocated for the value. </param>
	/// <param name="Length"> On output contains a characteristic value length in
	///   bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
    int ReadCharacteristicValue(const wclGattCharacteristic& Characteristic, const wclGattOperationFlag Flag,
		const wclGattProtectionLevel Protection, unsigned char*& Value, unsigned long& Length);
    /// <summary> The method reads all the descriptors available for the
    ///   specified characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Descriptors"> On output contains the list of the
    ///   characteristic's descriptors. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattDescriptors" />
    int ReadDescriptors(const wclGattCharacteristic& Characteristic, const wclGattOperationFlag Flag,
		wclGattDescriptors& Descriptors);
    /// <summary> The method reads the value of the specified
    ///   descriptor. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A descriptor's value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattDescriptor" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
    /// <seealso cref="wclGattDescriptorValue" />
    int ReadDescriptorValue(const wclGattDescriptor& Descriptor, const wclGattOperationFlag Flag,
		const wclGattProtectionLevel Protection, wclGattDescriptorValue& Value);
    /// <summary> The method reads all the included services available for a
    ///   given service. </summary>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    int ReadIncludedServices(const wclGattService& Service, const wclGattOperationFlag Flag,
		wclGattServices& Services);
    /// <summary> Reads available services from a remote Bluetooth LE
    ///   device. </summary>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    int ReadServices(const wclGattOperationFlag Flag, wclGattServices& Services);

	/// <summary> The method writes the specified characteristic value to the
    ///   Bluetooth device. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A pointer to the characteristic's value </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
	/// <param name="WriteKind"> The write operation mode. </param>
    /// <seealso cref="wclGattCharacteristic" />
	/// <seealso cref="wclGattProtectionLevel" />
	/// <seealso cref="wclGattWriteKind" />
    int WriteCharacteristicValue(wclGattCharacteristic Characteristic,
		const wclGattProtectionLevel Protection, const unsigned char* const Value,
		const unsigned long Length, const wclGattWriteKind WriteKind);
    /// <summary> The method writes the specified descriptor value to the
    ///   Bluetooth device. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <param name="Value"> A descriptor's value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattDescriptor" />
	/// <seealso cref="wclGattProtectionLevel" />
    /// <seealso cref="wclGattDescriptorValue" />
    int WriteDescriptorValue(const wclGattDescriptor& Descriptor, const wclGattProtectionLevel Protection,
		const wclGattDescriptorValue& Value);

	/// <summary> Writes the client configuration descriptor to the
    ///   device. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is interested. </param>
    /// <param name="Subscribe"> The value indicates should we subscribe
    ///   or unsubscribe from the characteristic value changes. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> In order to receive notifications about characteristic
    ///   value changes the client must set the Client Configuration Descriptor.
    ///   An application can use this method to do it in easy way. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
	int WriteClientConfiguration(const wclGattCharacteristic& Characteristic,
		const bool Subscribe, const wclGattOperationFlag Flag,
		const wclGattProtectionLevel Protection);

    /// <summary> Subscribes for the characteristic changes
    ///   notifications. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is interested. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The method does not change Client Configuration Descriptor
    ///   value. Application must do it by itself or by calling
    ///   the <c>WriteClientConfiguration</c> method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
	int Subscribe(const wclGattCharacteristic& Characteristic);
    /// <summary> Unsubscribes from the characteristic changes
    ///   notifications. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is not interested any more. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The method does not change Client Configuration Descriptor
    ///   value. Application must do it by itself or by calling
    ///   the <c>WriteClientConfiguration</c> method. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
	int Unsubscribe(const wclGattCharacteristic& Characteristic);

    /// <summary> Connects to a remote device. </summary>
    /// <param name="Address"> A remote device MAC address. </param>
	/// <param name="ConnectOnRead"> A Boolean indicates whether a connection
	///   should made during <c>Connect</c> call or on first services
	///   read. <c>True</c> indicates that the connection should be executed
	///   on first services read on when OS decided to do that. </param>
	/// <param name="ForceNotifications"> A Boolean indicates that the
	///   notifications (and/or indications) should be forced. This should be
	///   set to <c>True</c> for some boards (such as <c>Bluno</c>, <c>Bluno
	///   Mega</c> and some others) that do not have <c>Characteristic
	///   Client Configuration Descriptor</c>. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The method starts a connection operation to a remote device.
    ///   If the method success that does not mean that the connection was
    ///   established. That just means that the connection operation was
    ///   started. The real connection result will be passed to the
    ///   <c>OnConnect</c> event handler. </remarks>
    int Connect(const __int64 Address, const bool ConnectOnRead,
		const bool ForceNotifications);

	/// <summary> Gets the current connection parameters. </summary>
	/// <param name="Params"> If the function completed with success on output
	///   contains the current connection parameters. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParameters" />
	int GetConnectionParams(wclBluetoothLeConnectionParameters& Params);
	/// <summary> Request the connection parameters change to the specified
	///   preferred connection parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> When performing firmware updates, higher throughput is
	///   necessary to complete the operation swiftly for the user. In those
	///   scenarios, you should request <c>ppThroughputOptimized</c> connection
	///   parameters for the duration of the firmware update. That will reduce
	///   the number of concurrent connections to other Bluetooth peripherals,
	///   and should be used sparingly. </para>
	///   <para> Conversely, when connecting to multiple LE devices
	///   concurrently, you should use <c>ppPowerOptimized</c>. That will
	///   increase the acceptable peripheral latency for the connection,
	///   reducing the interval at which the LE device must respond to the
	///   host OS. That allows the local Bluetooth radio to schedule more
	///   connections concurrently, and reduces power usage on both the host OS
	///   and on the peripheral device. </para>
	///   <para> If the connection parameters were changed successfully the
	///   <c>OnConnectionParamsChanged</c> even fires. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersType" />
	int SetConnectionParams(const wclBluetoothLeConnectionParametersType Params);
	/// <summary> Request the connection parameters change to the specified
	///   preferred connection parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   value. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks><para> If the connection parameters were changed successfully
	///   the <c>OnConnectionParamsChanged</c> even fires. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersValue" />
	int SetConnectionParams(const wclBluetoothLeConnectionParametersValue& Params);

	/// <summary> Reads the maximum PDU size for the current connection. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum PDU size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> The PDU size includes header and payload. For example if
	///   PDU size is 23 bytes the allowed payload is 20 bytes. </remarks>
	int GetMaxPduSize(unsigned short& Size);
	
	/// <summary> Reads the Bluetooth LE physical layer (PHY)
	///   information. </summary>
	/// <param name="Info"> If the method completed with success on output
	///   contains the connection PHY information. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported on Windows 11 and above. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionPhy" />
	int GetConnectionPhyInfo(wclBluetoothLeConnectionPhy& Info);

    /// <summary> Gets a remote device MAC address. </summary>
    /// <returns> The remote device MAC address. </returns>
    __int64 GetAddress() const;
	/// <summary> Gets a remote device MAC address. </summary>
    /// <value> The remote device MAC address. </value>
	__declspec(property(get = GetAddress)) __int64 Address;

	/// <summary> Gets connection mode. </summary>
	/// <returns> The Boolean indicates the connection mode. </returns>
	/// <remarks> If this property set to <c>True</c> the connection to a target
	///   device will be executed on first services read or when the OS decided
	///   to do that. If the property is <c>False</c> the connection will be
	///   executed (if possible) on <c>Connect</c> call. </remarks>
	bool GetConnectOnRead() const;
	/// <summary> Gets connection mode. </summary>
	/// <value> The Boolean indicates the connection mode. </value>
	/// <remarks> If this property set to <c>True</c> the connection to a target
	///   device will be executed on first services read or when the OS decided
	///   to do that. If the property is <c>False</c> the connection will be
	///   executed (if possible) on <c>Connect</c> call. </remarks>
	__declspec(property(get = GetConnectOnRead)) bool ConnectOnRead;

	/// <summary> Gets the notifications mode. </summary>
	/// <returns> The Boolean indicates the notifications mode. </returns>
	/// <remarks> If this property set to <c>True</c> the characteristic value
	///   changes notification (and/or indication) will work correctly with
	///   some boards (such as <c>Bluno</c>, <c>Bluno Meag</c> and some others)
	///   that do not have <c>Characteristic Client Configucation
	///   Descriptor</c>. </remarks>
	bool GetForceNotifications() const;
	/// <summary> Gets the notifications mode. </summary>
	/// <value> The Boolean indicates the notifications mode. </value>
	/// <remarks> If this property set to <c>True</c> the characteristic value
	///   changes notification (and/or indication) will work correctly with
	///   some boards (such as <c>Bluno</c>, <c>Bluno Meag</c> and some others)
	///   that do not have <c>Characteristic Client Configucation
	///   Descriptor</c>. </remarks>
	__declspec(property(get = GetForceNotifications)) bool ForceNotifications;

    /// <summary> Gets the connection owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

    /// <summary> The event fires when a subscribed characteristic value has
    ///   been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Handle"> A changed characteristic handle. </param>
	/// <param name="Value"> A pointer to the characteristic value. </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
	/// <remarks> <para> The <c>Value</c> parameter is valid only inside the event
	///   handler. If an application needs to use it outside the event handler
	///   it must be copied. </para>
	///   <para> To receive characteristic value change events an application
    ///   must first subscribe for characteristic changes notification
	///   by calling <c>Subscribe</c> method. </para> </remarks>
	wclGattCharacteristicChangedEvent(OnCharacteristicChanged);
	/// <summary> The event fires when the connection parameters
	///   changed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <remarks> <para> Once this event received an application can use the
	///   <c>GetConnectionParams</c> method to get the current connection
	///   parameters. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	wclNotifyEvent(OnConnectionParamsChanged);
	/// <summary> The event fires when the connection PHY changed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    /// <remarks> <para> Once this event received an application can use the
    ///   <c>GetConnectionParams</c> method to get the current connection
    ///   parameters. </para>
    ///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </para> </remarks>
    wclNotifyEvent(OnConnectionPhyChanged);
	/// <summary> The event fires when the maximum PDU size changed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <remarks> Once the event fires an application can use the
	///   <c>GetMaxPduSize</c> method to read the current maximum PDU
	///   size. </remarks>
    wclNotifyEvent(OnMaxPduSizeChanged);
};

/// <summary> The base class for local GATT attributes (characteristics,
///   services). </summary>
class CwclGattLocalAttribute
{
	DISABLE_COPY(CwclGattLocalAttribute);
	
private:
	RTL_CRITICAL_SECTION	FCS;
	wclGattUuid				FUuid;

protected:
	/// <summary> Enters the GATT local attribute protection critical
	///   section. </summary>
	void Enter() const;
	/// <summary> Leaves the GATT local attribute protection critical
	///   section. </summary>
	void Leave() const;

public:
	/// <summary> Creates new local GATT attribute. </summary>
	/// <param name="Uuid"> The attribute's UUID. </param>
	/// <seealso cref="wclGattUuid" />
	CwclGattLocalAttribute(const wclGattUuid& Uuid);
	/// <summary> Frees the object. </summary>
    virtual ~CwclGattLocalAttribute();
	
	/// <summary> Gets the attribute's UUID. </summary>
	/// <returns> The attribute's UUID. </returns>
	/// <seealso cref="wclGattUuid" />
	wclGattUuid GetUuid() const;
	/// <summary> Gets the attribute's UUID. </summary>
	/// <value> The attribute's UUID. </value>
	/// <seealso cref="wclGattUuid" />
	__declspec(property(get = GetUuid)) wclGattUuid Uuid;
};

/// <summary> This class represents a local GATT characteristic. </summary>
/// <remarks> An application must not create or destroy this class directly.
///   Instead of that an application must use methods of the
///   <seealso cref="CwclGattLocalService" /> class. </remarks>
/// <seealso cref="CwclGattLocalAttribute" />
class CwclGattLocalCharacteristic : public CwclGattLocalAttribute
{
	DISABLE_COPY(CwclGattLocalCharacteristic);
	
private:
	friend class CwclGattLocalService;
	friend class CwclGattServerClient;

	typedef std::list<CwclGattServerClient*> CLIENTS;
	
	bool									FAdded;
	CLIENTS*								FClients;
	int										FError;
	wclGattLocalCharacteristicParameters	FParams;
	CwclGattLocalService*					FService;

	bool IsNotifiable() const;

	void AddClient(CwclGattServerClient* const Client);
	void RemoveClient(CwclGattServerClient* const Client);
	
	// This method called by the local GATT service object to add the
	// characteristic. This method is called in separate thread.
	int Add();
	// This method called by the local GATT service object to remove the
	// characteristic. It is guaranteed that this method will be called only
	// if characteristic has been added (cal; to the Add method was success).
	// This method is called in separate thread.
	int Remove();
	
protected:
	/* HAL methods. */

	/// <summary> The method implements a driver specific code to add
	///   characteristic to the local GATT service. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that adds the GATT characteristic. </remarks>
	virtual int HalAdd() = 0;
	/// <summary> The method implements a driver specific code to remove
	///   characteristic from the local GATT service. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that removes the GATT characteristic. </remarks>
	virtual int HalRemove() = 0;
	/// <summary> The function implements a driver specific code to send
	///   notification to the given subscribed client. </summary>
	/// <param name="Address"> The client's MAC address. </param>
	/// <param name="Data"> The pointer to the notification data. </param>
	/// <param name="Size"> The notification data size in bytes. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that sends notification to the given subscribed
	///   client. </remarks>
	virtual int HalNotify(const __int64 Address, const unsigned char* const Data,
		const unsigned long Size) const = 0;

public:
	/// <summary> Creates new local GATT characteristic. </summary>
	/// <param name="Service"> The local GATT service object that owns the
	///   characteristic. If this parameter is <c>NULL</c> the
	///   <see cref="wclECritical" /> exception raises. </param>
	/// <param name="Uuid"> The characteristic's UUID. </param>
	/// <param name="Params"> The characteristic's parameters. </param>
	/// <remarks> An application must not create this class directly.
	///   Instead of that an application must use methods of the
	///   <see cref="CwclGattLocalService" /> class. </remarks>
	/// <seealso cref="CwclGattLocalService" />
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="wclGattLocalCharacteristicParameters" />
	/// <exception cref="wclECritical"></exception>
	CwclGattLocalCharacteristic(CwclGattLocalService* const Service,
		const wclGattUuid& Uuid, const wclGattLocalCharacteristicParameters& Params);
	/// <summary> Frees the object. </summary>
	virtual ~CwclGattLocalCharacteristic();
	
	/// <summary> Sends notification to the given subscribed client. </summary>
	/// <param name="Address"> The client's MAC address. </param>
	/// <param name="Data"> The pointer to the notification data. </param>
	/// <param name="Size"> The notification data size in bytes. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Notify(const __int64 Address, const unsigned char* const Data,
		const unsigned long Size) const;
	
	/// <summary> Gets the characteristic's status. </summary>
	/// <returns> <c>True</c> if the characteristic has been successfully added to
	///   the local GATT service, <c>False</c> otherwise. </returns>
	bool GetAdded() const;
	/// <summary> Gets the characteristic's status. </summary>
	/// <value> <c>True</c> if the characteristic has been successfully added to
	///   the local GATT service, <c>False</c> otherwise. </value>
	__declspec(property(get = GetAdded)) bool Added;

	/// <summary> Gets the subscribed client by its index. </summary>
	/// <param name="Index"> The client's index. The <c>Index</c> parameter
	///   must be in range between <c>0</c> and <c>Count - 1</c>. If the
	///   <c>Index</c> is out of range the <see cref="wclEInvalidArgument" />
	///   exception raises. </param>
	/// <returns> The <see cref="CwclGattServerClient" /> object. </returns>
    /// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
    CwclGattServerClient* GetClients(const size_t Index) const;
	/// <summary> Gets the subscribed client by its index. </summary>
	/// <value> The <see cref="CwclGattServerClient" /> object. </value>
    /// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetClients)) CwclGattServerClient* Clients[];

	/// <summary> Gets the subscribed clients count. </summary>
    /// <returns> The subscribed clients count. </returns>
    size_t GetCount() const;
	/// <summary> Gets the subscribed clients count. </summary>
    /// <value> The subscribed clients count. </value>
	__declspec(property(get = GetCount)) size_t Count;

	/// <summary> Gets the characteristic's publishing error. </summary>
	/// <returns> One of the WCL error code that indicates why characteristic
	///   has not been added. </returns>
	/// <remarks> If adding characteristic to the service was failed this
	///   property contains the failure reason code. </remarks>
	int GetError() const;
	/// <summary> Gets the characteristic's publishing error. </summary>
	/// <value> One of the WCL error code that indicates why characteristic
	///   has not been added. </value>
	/// <remarks> If adding characteristic to the service was failed this
	///   property contains the failure reason code. </remarks>
	__declspec(property(get = GetError)) int Error;

	/// <summary> Gets the characteristic's parameters. </summary>
	/// <returns> The characteristic's parameters. </returns>
	/// <seealso cref="wclGattLocalCharacteristicParameters" />
	wclGattLocalCharacteristicParameters GetParams() const;
	/// <summary> Gets the characteristic's parameters. </summary>
	/// <value> The characteristic's parameters. </value>
	/// <seealso cref="wclGattLocalCharacteristicParameters" />
	__declspec(property(get = GetParams)) wclGattLocalCharacteristicParameters Params;

	/// <summary> Gets the GATT service object that owns the
	///   characteristic. </summary>
	/// <returns> The local GATT service object. </returns>
	/// <seealso cref="CwclGattLocalService" />
	CwclGattLocalService* GetService() const;
	/// <summary> Gets the GATT service object that owns the
	///   characteristic. </summary>
	/// <value> The local GATT service object. </value>
	/// <seealso cref="CwclGattLocalService" />
	__declspec(property(get = GetService)) CwclGattLocalService* Service;
};

/// <summary> This class represents a local GATT service. </summary>
/// <remarks> An application must not create or destroy this class directly.
///   Instead of that an application must use methods of the
///   <see cref="CwclGattServerConnection" /> classes. </remarks>
/// <seealso cref="CwclGattLocalAttribute" />
class CwclGattLocalService : public CwclGattLocalAttribute
{
	DISABLE_COPY(CwclGattLocalService);

private:
	friend class CwclGattServerConnection;

	typedef std::list<CwclGattLocalCharacteristic*> CHARS;

	bool						FAdded;
	int							FError;
	CHARS*						FCharacteristics;
	CwclGattServerConnection*	FServer;

	bool					FConnectable;
	bool					FDiscoverable;

	// Internal helper methods.
	int AddAllCharacteristics();
	void ClearAllCharacteristics();
	void DeleteSelectedCharacteristic(const size_t Index);
	void RemoveAddedCharacteristics();
	void RemoveAllCharacteristics();

	// This method called by the GATT server connection object to create and add
	// the service. This method is called in separate thread.
	int Add();
	// This method called by the GATT server connection to remove and destroy
	// the service. It is guaranteed that this method will be called only
	// if characteristic has been added (cal; to the Add method was success).
	// This method is called in separate thread.
	int Remove();
	
protected:
	/* HAL methods. */

	/// <summary> The method implements a driver specific code to add
	///   local GATT service to the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that adds the GATT service. </remarks>
	virtual int HalAdd() = 0;
	/// <summary> The method implements a driver specific code to create
	///   local GATT service to the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that creates the GATT service. </remarks>
	virtual int HalCreate() = 0;
	/// <summary> The method implements a driver specific code to destroy
	///   local GATT service from the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that destroys the GATT service. </remarks>
	virtual int HalDestroy() = 0;
	/// <summary> The method implements a driver specific code to remove
	///   local GATT service from the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to implement a
	///   driver specified code that removes the GATT service. </remarks>
	virtual int HalRemove() = 0;
	
	/// <summary> The function creates a driver specific GATT characteristic
	///   object. </summary>
	/// <param name="Uuid"> The characteristic UUID. </param>
	/// <param name="Params"> The characteristic parameters. </param>
	/// <param name="Characteristic"> If the function completed with success
	///   the parameter contains just created characteristic object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to create a
	///   GATT characteristic. </remarks>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="wclGattLocalCharacteristicParameters" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual int HalCreateCharacteristic(const wclGattUuid& Uuid,
		const wclGattLocalCharacteristicParameters& Params,
		CwclGattLocalCharacteristic*& Characteristic) = 0;
	
public:
	/// <summary> Creates new Local GATT service. </summary>
	/// <param name="Server"> The GATT server connection object that owns
	///   the service. If this parameter is <c>NULL</c> the
	///   <seealso cref="wclECritical" /> raises. </param>
	/// <param name="Uuid"> The service's UUID. </param>
	/// <remarks> An application must not create this class directly.
	///   Instead of that an application must use methods of high-level
	///   classes. </remarks>
	/// <seealso cref="CwclGattServerConnection" />
	/// <seealso cref="wclGattUuid" />
	/// <exception cref="wclECritical"></exception>
	CwclGattLocalService(CwclGattServerConnection* const Server, const wclGattUuid& Uuid);
	/// <summary> Frees the object. </summary>
	/// <remarks> An application must not destroy this class directly.
	///   Instead of that an application must use methods of high-level
	///   classes. </remarks>
	virtual ~CwclGattLocalService();
	
	/// <summary> Creates new characteristic and adds it to the service
	///   characteristics list. </summary>
	/// <param name="Uuid"> The characteristic UUID. </param>
	/// <param name="Params"> The characteristic parameters. </param>
	/// <param name="Characteristic"> If the method completed with success the
	///   parameters contains a just created GATT characteristic
	///   object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="wclGattLocalCharacteristicParameters" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	int AddCharacteristic(const wclGattUuid& Uuid, const wclGattLocalCharacteristicParameters& Params,
		CwclGattLocalCharacteristic*& Characteristic);
	/// <summary> Clears the characteristics list. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int ClearCharacteristics();
	/// <summary> Deletes the characteristic with given index. </summary>
	/// <param name="Index"> The service's index. The parameter must be in range
	///   between 0 and ServicesCount - 1. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int DeleteCharacteristic(const size_t Index);

	/// <summary> Gets a boolean that indicates if the GATT service is
    ///   connectable. </summary>
    /// <returns> A boolean that indicates if the GATT service is
    ///   connectable. </returns>
    bool GetConnectable() const;
	/// <summary> Sets a boolean that indicates if the GATT service is
	///   connectable. </summary>
	/// <param name="Value"> A boolean that indicates if the GATT service is
	///   connectable. </param>
	/// <remarks> If the service has been published and an application
	///   changes the property the <see cref="wclEGattServer" /> exception
	///   raises. </remarks>
	/// <exception cref="wclEGattServer"></exception>
	void SetConnectable(const bool Value);
	/// <summary> Gets or sets a boolean that indicates if the GATT service is
    ///   connectable. </summary>
    /// <value> A boolean that indicates if the GATT service is
    ///   connectable. </value>
    /// <remarks> If the service has been published and an application
    ///   changes the property the <see cref="wclEGattServer" /> exception
    ///   raises. </remarks>
	/// <exception cref="wclEGattServer"></exception>
	__declspec(property(get = GetConnectable, put = SetConnectable)) bool Connectable;

	/// <summary> Gets a boolean indicating that the GATT service is
	///   discoverable. </summary>
	/// <returns> A boolean indicating that the GATT service is
	///   discoverable. </returns>
	bool GetDiscoverable() const;
	/// <summary> Sets a boolean indicating that the GATT service is
	///   discoverable. </summary>
	/// <param name="Value"> A boolean indicating that the GATT service is
	///   discoverable. </param>
	/// <remarks> If the service has been published and an application
	///   changes the property the <see cref="wclEGattServer" /> exception
	///   raises. </remarks>
	/// <exception cref="wclEGattServer"></exception>
	void SetDiscoverable(const bool Value);
	/// <summary> Gets or sets a boolean indicating that the GATT service is
    ///   discoverable. </summary>
    /// <value> A boolean indicating that the GATT service is
    ///   discoverable. </value>
    /// <remarks> If the service has been published and an application
    ///   changes the property the <see cref="wclEGattServer" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEGattServer"></exception>
	__declspec(property(get = GetDiscoverable, put = SetDiscoverable)) bool Discoverable;
	
	/// <summary> Gets the service state. </summary>
	/// <returns> <c>True</c> if the service is added and published. <c>False</c>
	///   otherwise. </returns>
	bool GetAdded() const;
	/// <summary> Gets the service state. </summary>
	/// <value> <c>True</c> if the service is added and published. <c>False</c>
	///   otherwise. </value>
	__declspec(property(get = GetAdded)) bool Added;

	/// <summary> Gets the GATT characteristic by its index. </summary>
	/// <param name="Index"> The characteristic's index. The parameter must be
	///   in range between 0 and CharacteristicsCount - 1. If the parameter is
	///   out of range the <see cref="wclEInvalidArgument" /> exception
	///   raises. </param>
	/// <returns> The local GATT characteristic. </returns>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclGattLocalCharacteristic* GetCharacteristics(const size_t Index) const;
	/// <summary> Gets the GATT characteristic by its index. </summary>
	/// <value> The local GATT characteristic. </value>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetCharacteristics)) CwclGattLocalCharacteristic* Characteristics[];

	/// <summary> Gets the characteristics count. </summary>
	/// <returns> The characteristics count. </returns>
	size_t GetCharacteristicsCount() const;
	/// <summary> Gets the characteristics count. </summary>
	/// <value> The characteristics count. </value>
	__declspec(property(get = GetCharacteristicsCount)) size_t CharacteristicsCount;

	/// <summary> Gets the service's publishing result code. </summary>
	/// <returns> One of WCL errors code indicates the publishing result. </returns>
	/// <remarks> If publishing the service was failed this property contains the
	///   failure reason code. </remarks>
	int GetError() const;
	/// <summary> Gets the service's publishing result code. </summary>
	/// <value> One of WCL errors code indicates the publishing result. </value>
	/// <remarks> If publishing the service was failed this property contains the
	///   failure reason code. </remarks>
	__declspec(property(get = GetError)) int Error;

	/// <summary> Gets the GATT server object that owns the service. </summary>
	/// <returns> The GATT server object. </returns>
	/// <seealso cref="CwclGattServerConnection" />
	CwclGattServerConnection* GetServer() const;
	/// <summary> Gets the GATT server object that owns the service. </summary>
	/// <value> The GATT server object. </value>
	/// <seealso cref="CwclGattServerConnection" />
	__declspec(property(get = GetServer)) CwclGattServerConnection* Server;
};

/// <summary> The base class for local GATT characteristic operation
///   requests. </summary>
/// <remarks> An application must never create or destroy this class.
///   The class is created and released internally when needed. </remarks>
class CwclGattLocalCharacteristicRequest
{
	DISABLE_COPY(CwclGattLocalCharacteristicRequest);

private:
	unsigned long	FOffset;
	bool			FProcessed;
	
protected:
	/// <summary> Sets the processed flag. </summary>
	/// <param name="Error"> The operation result code. </param>
	void SetProcessed(const int Error);
	/// <summary> Checks if the request has already been processed. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int CheckProcessed();
	
	/// <summary> Responds to the request with an error. </summary>
    /// <param name="Error"> The GATT operation error code. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> A derived class must override this method to provide
    ///   hardware dependent code that sends a error respond. </para>
    ///   <para> An application must call this method in case if there
    ///   is an error appeared during request processing. The <c>Error</c> is
    ///   one of the Wireless Communication Library GATT error. </para>
    ///   <para> The <see cref="WCL_E_INVALID_ARGUMENT" /> result indicates that
    ///   the error code passed to the method is not one from the GATT errors
    ///   list. </para>
    ///   <para> Valid error codes are: </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_HANDLE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_READ_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_WRITE_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_PDU" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHENTICATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_REQUEST_NOT_SUPPORTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_OFFSET" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHORIZATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_PREPARE_QUEUE_FULL" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_FOUND" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_LONG" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION_KEYSIZE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_ATTRIBUTE_VALUE_LENGTH" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNLIKELY" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNSUPPORTED_GROUP_TYPE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_RESOURCES" /> </para>
    /// </remarks>
    virtual int HalRespondWithError(const int Error) = 0;
	
public:
	/// <summary> Creates new object. </summary>
	/// <param name="Offset"> A data offset. </param>
	/// <remarks> An application must not create this class. It is created
	///   internally when needed. </remarks>
	CwclGattLocalCharacteristicRequest(const unsigned long Offset);
	/// <summary> Frees the object. </summary>
	/// <remarks> An application must not destroy this class. Instead of
	///   calling destructor an application must call the <c>Release</c>
	///   method. </remarks>
	virtual ~CwclGattLocalCharacteristicRequest();

    /// <summary> Responds to the request with an error. </summary>
    /// <param name="Error"> The GATT operation error code. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> An application must call this method in case if there
    ///   is an error appeared during request processing. The <c>Error</c> is
    ///   one of the Wireless Communication Library GATT error. </para>
    ///   <para> The <see cref="WCL_E_INVALID_ARGUMENT" /> result indicates that
    ///   the error code passed to the method is not one from the GATT errors
    ///   list. </para>
    ///   <para> Valid error codes are: </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_HANDLE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_READ_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_WRITE_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_PDU" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHENTICATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_REQUEST_NOT_SUPPORTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_OFFSET" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHORIZATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_PREPARE_QUEUE_FULL" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_FOUND" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_LONG" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION_KEYSIZE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_ATTRIBUTE_VALUE_LENGTH" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNLIKELY" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNSUPPORTED_GROUP_TYPE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_RESOURCES" /> </para>
    /// </remarks>
    virtual int RespondWithError(const int Error);
	
	/// <summary> Gets the data offset. </summary>
    /// <returns> The data offset. </returns>
	unsigned long GetOffset() const;
	/// <summary> Gets the data offset. </summary>
    /// <value> The data offset. </value>
	__declspec(property(get = GetOffset)) unsigned long Offset;
};

/// <summary> The class represents a GATT characteristic read
///   requests. </summary>
/// <remarks> An application must never create or destroy this class.
///   The class is created and released internally when needed. </remarks>
/// <seealso cref="CwclGattLocalCharacteristicRequest" />
class CwclGattLocalCharacteristicReadRequest : public CwclGattLocalCharacteristicRequest
{
	DISABLE_COPY(CwclGattLocalCharacteristicReadRequest);

private:
	unsigned long	FSize;
	
protected:
	/// <summary> Sends the specified data to the connected client in respond to
	///   a read request. </summary>
	/// <param name="Data"> The pointer to the data. </param>
	/// <param name="Size"> The data length. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide hardware
    ///   dependent code that sends a data to a remote connected GATT
    ///   client. </remarks>
    virtual int HalRespond(void* const Data, const unsigned long Size) = 0;
	
public:
	/// <summary> Creates new object. </summary>
	/// <param name="Offset"> A data offset. </param>
	/// <param name="Size"> A read buffer size. </param>
	/// <remarks> An application must not create this class. It is created
	///   internally when needed. </remarks>
	CwclGattLocalCharacteristicReadRequest(const unsigned long Offset,
		const unsigned long Size);
	
    /// <summary> Sends the specified data to the connected client in respond to
    ///   a read request. </summary>
    /// <param name="Data"> The pointer to the data. </param>
    /// <param name="Size"> The data length. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int Respond(void* const Data, const unsigned long Size);

	/// <summary> Gets the read buffer size. </summary>
	/// <returns> The read buffer size. </returns>
	unsigned long GetSize() const;
	/// <summary> Gets the read buffer size. </summary>
	/// <value> The read buffer size. </value>
	__declspec(property(get = GetSize)) unsigned long Size;
};

/// <summary> The class represents a GATT characteristic write
///   requests. </summary>
/// <remarks> An application must never create or destroy this class.
///   The class is created and released internally when needed. </remarks>
/// <seealso cref="CwclGattLocalCharacteristicRequest" />
class CwclGattLocalCharacteristicWriteRequest : public CwclGattLocalCharacteristicRequest
{
	DISABLE_COPY(CwclGattLocalCharacteristicWriteRequest);
	
private:
	void*			FData;
	unsigned long	FSize;
	bool			FWithResponse;
	
protected:
	/// <summary> Sends a response to the connected client in respond to a write
	///   request. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide hardware
	///   dependent code that sends a data to a remote connected GATT
	///   client. </remarks>
	virtual int HalRespond() = 0;
	
public:
	/// <summary> Creates new object. </summary>
	/// <param name="Offset"> A data offset. </param>
	/// <param name="Data"> The pointer to the data. </param>
	/// <param name="Size"> The data length. </param>
	/// <param name="WithResponse"> The GATT write operation flag. </param>
	/// <remarks> An application must not create this class. It is created
	///   internally when needed. </remarks>
	CwclGattLocalCharacteristicWriteRequest(const unsigned long Offset, void* const Data,
		const unsigned long Size, const bool WithResponse);
	
	/// <summary> Sends a response to the connected client in respond to a write
	///   request. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This method must be called only in case the write operation
    ///   was made with required response (the <c>WithResponse</c> property is
    ///   <c>True</c>. </remarks>
    int Respond();
    /// <summary> Responds to the request with an error. </summary>
    /// <param name="Error"> The GATT operation error code. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> An application must call this method in case if there
    ///   is an error appeared during request processing. The <c>Error</c> is
    ///   one of the Wireless Communication Library GATT error. </para>
    ///   <para> The <see cref="WCL_E_INVALID_ARGUMENT" /> result indicates that
    ///   the error code passed to the method is not one from the GATT errors
    ///   list. </para>
    ///   <para> Valid error codes are: </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_HANDLE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_READ_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_WRITE_NOT_PERMITTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_PDU" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHENTICATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_REQUEST_NOT_SUPPORTED" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_OFFSET" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_AUTHORIZATION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_PREPARE_QUEUE_FULL" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_FOUND" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_ATTRIBUTE_NOT_LONG" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION_KEYSIZE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INVALID_ATTRIBUTE_VALUE_LENGTH" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNLIKELY" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_ENCRYPTION" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_UNSUPPORTED_GROUP_TYPE" /> </para>
    ///   <para> <see cref="WCL_E_BLUETOOTH_LE_INSUFFICIENT_RESOURCES" /> </para>
    /// </remarks>
    virtual int RespondWithError(const int Error) override;
	
	/// <summary> Gets the pointer to the data. </summary>
    /// <returns> The pointer to the data bytes. </returns>
    /// <remarks> This pointer is valid only inside an event handler. If an
    ///   application needs to process the data outside the event handler it must
    ///   copy the data. </remarks>
	void* GetData() const;
	/// <summary> Gets the pointer to the data. </summary>
	/// <value> The pointer to the data bytes. </value>
    /// <remarks> This pointer is valid only inside an event handler. If an
    ///   application needs to process the data outside the event handler it must
    ///   copy the data. </remarks>
	__declspec(property(get = GetData)) void* Data;

	/// <summary> Gets the data size. </summary>
    /// <returns> The data size in bytes. </returns>
	unsigned long GetSize() const;
	/// <summary> Gets the data size. </summary>
    /// <value> The data size in bytes. </value>
	__declspec(property(get = GetSize)) unsigned long Size;
	
	/// <summary> Gets the write operation flag. </summary>
    /// <returns> The GATT write operation flag. </returns>
    /// <remarks> If this property is <c>True</c> an application must response
    ///   to the write request with <c>Respond</c> or <c>RespondWithError</c>
    ///   method. </remarks>
	bool GetWithResponse() const;
	/// <summary> Gets the write operation flag. </summary>
    /// <value> The GATT write operation flag. </value>
    /// <remarks> If this property is <c>True</c> an application must response
    ///   to the write request with <c>Respond</c> or <c>RespondWithError</c>
    ///   method. </remarks>
	__declspec(property(get = GetWithResponse)) bool WithResponse;
};

/// <summary> The base class for a driver specific GATT server client
///   implementation parameters. </summary>
class CwclBluetoothGattServerClientParams
{
	DISABLE_COPY(CwclBluetoothGattServerClientParams);
	
public:
	/// <summary> Creates new parameters object. </summary>
	CwclBluetoothGattServerClientParams();
	/// <summary> Frees the object. </summary>
	virtual ~CwclBluetoothGattServerClientParams();
};

/// <summary> The class represents a GATT client connected to the GATT
///   server. </summary>
/// <remarks> An application must not create and destroy objects of this
///   class directly. The objects of this class managed by the
///   <see cref="CwclGattServerConnection" />. </remarks>
/// <seealso cref="CwclGattServerConnection" />
class CwclGattServerClient
{
	DISABLE_COPY(CwclGattServerClient);
	
private:
	typedef std::list<CwclGattLocalCharacteristic*> CHARACTERISTICS;

	friend class CwclGattServerConnection;

	__int64						FAddress;
	CHARACTERISTICS*			FCharacteristics;
	CwclGattServerConnection*	FConnection;

	/* Characteristics management. */
	
	void AddCharacteristic(CwclGattLocalCharacteristic* const Characteristic);
	void RemoveCharacteristic(CwclGattLocalCharacteristic* const Characteristic);

protected:
	/// <summary> The method called right after client connected. </summary>
	/// <param name="Params"> The additional driver-specific parameters that
	///   can be used during client initialization. Can be <c>nil</c> if
	///   the driver specific implementation does not need this. </param>
	/// <remarks> A derived class may override this method to provide additional
	///   initialization after the client connected to a GATT server. </remarks>
	/// <seealso cref="CwclBluetoothGattServerClientParams" />
	virtual void AfterConnect(
		CwclBluetoothGattServerClientParams* const Params);
	/// <summary> The method right after a client disconnected from the server
	///   and before the client will be destroyed. </summary>
	/// <remarks> A derived class may override this method to provide additional
	///   finalization after client disconnected from a GATT server. </remarks>
	virtual void AfterDisconnect();
	
	/// <summary> The method called right after the client subscribed to a
	///   characteristic. </summary>
	/// <param name="Characteristic"> A
	///   <see cref="CwclGattLocalCharacteristic" /> object represents the
	///   subscribed characteristic. </param>
	/// <remarks> A derived class may override this method to provide additional
	///   initialization after client subscribed to the
	///   characteristic. </remarks>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void AfterSubscribed(CwclGattLocalCharacteristic* const Characteristic);
	/// <summary> The method called right after the client unsubscribed from a
	///   characteristic. </summary>
	/// <param name="Characteristic"> A
	///   <see cref="CwclGattLocalCharacteristic" /> object represents the
	///   unsubscribed characteristic. </param>
	/// <remarks> A derived class may override this method to provide additional
	///   finalization after client unsubscribed from the
	///   characteristic. </remarks>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void AfterUnsubscribed(CwclGattLocalCharacteristic* const Characteristic);
	
	/// <summary> Provide a driver specific code to disconnect the client from a
	///   server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide a driver
	///   specific code. </remarks>
	virtual int HalDisconnect() = 0;

	/* Connection parameters. */
	
	/// <summary> Implements a hardware-dependent code to get the current
	///   connection parameters. </summary>
	/// <param name="Params"> If the function completed with success on output
	///   contains the current connection parameters. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParameters" />
	virtual int HalGetConnectionParams(wclBluetoothLeConnectionParameters& Params) = 0;
	/// <summary> Implements a hardware-dependent code to request the connection
    ///   parameters change to the specified preferred connection
    ///   parameters. </summary>
    /// <param name="Params"> The preferred Bluetooth LE connection parameters
    ///   type. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclBluetoothLeConnectionParametersType" />
    virtual int HalSetConnectionParams(const wclBluetoothLeConnectionParametersType Params) = 0;
    /// <summary> Implements a hardware-dependent code to request the connection
    ///   parameters change to the specified preferred connection
    ///   parameters. </summary>
    /// <param name="Params"> The preferred Bluetooth LE connection parameters
    ///   value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method. </remarks>
    /// <seealso cref="wclBluetoothLeConnectionParametersValue" />
    virtual int HalSetConnectionParams(const wclBluetoothLeConnectionParametersValue& Params) = 0;

	/// <summary> Provides a driver specific code to read the maximum
	///   notification size. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum notification size. If the method failed the
	///   value is undefined. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide a driver
	///   specific code. </remarks>
	virtual int HalGetMaxNotificationSize(unsigned short& Size) = 0;
	/// <summary> Implements a hardware-dependent code to read the maximum PDU
	///   size for the current connection. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum PDU size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	virtual int HalGetMaxPduSize(unsigned short& Size) = 0;
	
	/// <summary> Implements a hardware-dependent code to reads the Bluetooth LE
	///   physical layer (PHY) information. </summary>
	/// <param name="Info"> If the method completed with success on output
	///   contains the connection PHY information. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionPhy" />
	virtual int HalGetConnectionPhyInfo(wclBluetoothLeConnectionPhy& Info) = 0;
	
public:
	/// <summary> Creates new client object. </summary>
	/// <param name="Address"> The client's address. If the <c>Address</c> is
	///   <c>0</c> the <see cref="wclEInvalidArgument" /> raises. </param>
	/// <param name="Connection"> The <see cref="CwclGattServerConnection" />
	///   object that owns the client. If the <c>Connection</c> is <c>nil</c>
	///   the <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <remarks> An application must not create the objects of this class
	///   directly. </remarks>
	/// <seealso cref="CwclGattServerConnection" />
	/// <exception cref="wclEInvalidArgument"></exception>
    CwclGattServerClient(const __int64 Address,
		CwclGattServerConnection* const Connection);
	/// <summary> Frees the object. </summary>
	/// <remarks> An application must not destroy objects of this class
	///   directly. </remarks>
	virtual ~CwclGattServerClient();

	/// <summary> Disconnects the client from a server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Disconnect();

	/// <summary> Gets the current connection parameters. </summary>
    /// <param name="Params"> If the function completed with success on output
    ///   contains the current connection parameters. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </remarks>
    /// <seealso cref="wclBluetoothLeConnectionParameters" />
    int GetConnectionParams(wclBluetoothLeConnectionParameters& Params);
	/// <summary> Request the connection parameters change to the specified
    ///   preferred connection parameters. </summary>
    /// <param name="Params"> The preferred Bluetooth LE connection parameters
    ///   type. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> <para> When performing firmware updates, higher throughput is
    ///   necessary to complete the operation swiftly for the user. In those
    ///   scenarios, you should request <c>ppThroughputOptimized</c> connection
    ///   parameters for the duration of the firmware update. That will reduce
    ///   the number of concurrent connections to other Bluetooth peripherals,
    ///   and should be used sparingly. </para>
    ///   <para> Conversely, when connecting to multiple LE devices
    ///   concurrently, you should use <c>ppPowerOptimized</c>. That will
    ///   increase the acceptable peripheral latency for the connection,
    ///   reducing the interval at which the LE device must respond to the
    ///   host OS. That allows the local Bluetooth radio to schedule more
    ///   connections concurrently, and reduces power usage on both the host OS
    ///   and on the peripheral device. </para>
    ///   <para> If the connection parameters were changed successfully the
    ///   <c>OnConnectionParamsChanged</c> even fires. </para>
    ///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </para> </remarks>
    /// <seealso cref="wclBluetoothLeConnectionParametersType" />
    int SetConnectionParams(const wclBluetoothLeConnectionParametersType Params);
    /// <summary> Request the connection parameters change to the specified
    ///   preferred connection parameters. </summary>
    /// <param name="Params"> The preferred Bluetooth LE connection parameters
    ///   value. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks><para> If the connection parameters were changed successfully
    ///   the <c>OnConnectionParamsChanged</c> even fires. </para>
    ///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </para> </remarks>
    /// <seealso cref="wclBluetoothLeConnectionParametersValue" />
    int SetConnectionParams(const wclBluetoothLeConnectionParametersValue& Params);
	
	/// <summary> Reads the maximum notification size. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum notification size. If the method failed the
	///   value is undefined. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int GetMaxNotificationSize(unsigned short& Size);
	/// <summary> Reads the maximum PDU size for the current
	///   connection. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum PDU size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> The PDU size includes header and payload. For example if
	///   PDU size is 23 bytes the allowed payload is 20 bytes. </remarks>
	int GetMaxPduSize(unsigned short& Size);

	/// <summary> Reads the Bluetooth LE physical layer (PHY)
    ///   information. </summary>
    /// <param name="Info"> If the method completed with success on output
    ///   contains the connection PHY information. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 11 and above. </remarks>
    /// <seealso cref="wclBluetoothLeConnectionPhy" />
    int GetConnectionPhyInfo(wclBluetoothLeConnectionPhy& Info);
	
	/// <summary> Gets the client's address. </summary>
	/// <returns> The client's address. </returns>
	__int64 GetAddress() const;
	/// <summary> Gets the client's address. </summary>
	/// <value> The client's address. </value>
	__declspec(property(get = GetAddress)) __int64 Address;

	/// <summary> Gets the subscribed characteristic by its index. </summary>
	/// <param name="Index"> The characteristic's index. The <c>Index</c>
	///   parameter must be in range between <c>0</c> and <c>Count - 1</c>.
	///   If the <c>Index</c> is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <returns> The <see cref="CwclGattLocalCharacteristic" /> object. </returns>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclGattLocalCharacteristic* GetCharacteristics(const size_t Index) const;
	/// <summary> Gets the subscribed characteristic by its index. </summary>
	/// <value> The <see cref="CwclGattLocalCharacteristic" /> object. </value>
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetCharacteristics)) CwclGattLocalCharacteristic* Characteristics[];

	/// <summary> Gets the <see cref="CwclGattServerConnection" /> object that
	///   owns the client. </summary>
	/// <returns> The <see cref="CwclGattServerConnection" /> object. </returns>
	/// <seealso cref="CwclGattServerConnection" />
	CwclGattServerConnection* GetConnection() const;
	/// <summary> Gets the <see cref="CwclGattServerConnection" /> object that
	///   owns the client. </summary>
	/// <value> The <see cref="CwclGattServerConnection" /> object. </value>
	/// <seealso cref="CwclGattServerConnection" />
	__declspec(property(get = GetConnection)) CwclGattServerConnection* Connection;

	/// <summary> Gets the subscribed characteristics count. </summary>
	/// <returns> The subscribed characteristics count. </returns>
	size_t GetCount() const;
	/// <summary> Gets the subscribed characteristics count. </summary>
	/// <value> The subscribed characteristics count. </value>
	__declspec(property(get = GetCount)) size_t Count;

	/// <summary> Gets the client subscribed status. </summary>
	/// <returns> <c>True</c> if the client is subscribed to at least one
    ///   characteristic. <c>False</c> otherwise. </returns>
    bool GetSubscribed() const;
	/// <summary> Gets the client subscribed status. </summary>
	/// <value> <c>True</c> if the client is subscribed to at least one
    ///   characteristic. <c>False</c> otherwise. </value>
	__declspec(property(get = GetSubscribed)) bool Subscribed;
};

/// <summary> The "virtual" connection for the Bluetooth GATT Server </summary>
/// <remarks> An application must not create or use this class directly.
///   Instead of that an application must use high-level Bluetooth
///   components. </remarks>
/// <seealso cref="CwclCustomConnection" />
class CwclGattServerConnection : public CwclCustomConnection
{
	DISABLE_COPY(CwclGattServerConnection);
	
private:
	typedef std::list<CwclGattLocalService*> SERVICES;
	typedef std::list<CwclGattServerClient*> CLIENTS;

	CLIENTS*			FClients;
	HANDLE				FMutex;
	CwclBluetoothRadio*	FRadio;
	SERVICES*			FServices;
	
	/* Communication thread management. */

	// Communication thread.
	HANDLE	FThread;
	// Thread initialization result.
	int		FInitResult;
	// Thread initialization event.
	HANDLE	FInitEvent;
	// Thread termination event.
	HANDLE	FTermEvent;
	
	static UINT __stdcall _ThreadProc(LPVOID Param);
	void ThreadProc();

	/* Bulk notifications. */

	void NotifyDisconnected();
	void NotifyUnsubscribed();

	/* Clients management. */
	
	// Adds the client with given address to the clients list. Returns true
	// if client was created and added. Returns false if client was not created
	// but found in the list or if the client was not found and was not found in
	// the list. If the client was added or found the Client parameter is the
	// client object.
	bool AddClient(const __int64 Address, CwclGattServerClient*& Client);
	// Looks for the client with the given address in the clients list. Returns
	// the client object if found. Returns nil if not found.
	CwclGattServerClient* FindClient(const __int64 Address) const;
	// Deletes the client with the given address from the clients list. DOES NOT
	// destroy the found client object. Returns the client object that was
	// removed from the list. A caller is responsible to destroy the client
	// object!!!
	CwclGattServerClient* RemoveClient(const __int64 Address);
	
	// Called when connect/read/write/subscribe event received to simulate (or
	// process real) connection. Not all drivers provide event (in fact, no one
	// does) when remote client connected to the server. So we have to emulate
	// this. To do that we use read/write/subscribe events. Returns new
	// GATT server client object that can be used in other events.
	CwclGattServerClient* ClientConnected(const __int64 Address,
		CwclBluetoothGattServerClientParams* const Params);
	// Called when disconnect event received. Removes client from the list.
	void ClientDisconnected(const __int64 Address);

	/* Message processing. */
	
	void ProcessMaxPduSizeChangedMessage(const __int64 Address);
	void ProcessWriteMessage(const __int64 Address,
		CwclBluetoothGattServerClientParams* const Params,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicWriteRequest* const Request);
	void ProcessReadMessage(const __int64 Address,
		CwclBluetoothGattServerClientParams* const Params,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicReadRequest* const Request);
	void ProcessClientSubscribedMessage(const __int64 Address,
		CwclBluetoothGattServerClientParams* const Params,
		CwclGattLocalCharacteristic* const Characteristic);
	void ProcessClientUnsubscribedMessage(const __int64 Address,
		CwclGattLocalCharacteristic* const Characteristic);
	void ProcessNotifySizeChangedMessage(const __int64 Address);
	void ProcessConnectionParamsChangedMessage(const __int64 Address);
	void ProcessConnectionPhyChangedMessage(const __int64 Address);

protected:
	/* Internal methods. */
	
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message);
	
	/* Events. */
	
	/// <summary> Fires the <c>OnClientConnected</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a connected client. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoClientConnected(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnClientDisconnected</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a disconnected client. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoClientDisconnected(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnConnectionParamsChanged</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a disconnected client. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoConnectionParamsChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnConnectionPhyChanged</c> event. </summary>
    /// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that represents a disconnected client. </param>
    /// <seealso cref="CwclGattServerClient" />
	virtual void DoConnectionPhyChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnMaxPduSizeChanged</c> event. </summary>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoMaxPduSizeChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnNotificationSizeChanged</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a client which changed the maximum notification
	///   size. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoNotificationSizeChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnRead</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that requested read. </param>
	/// <param name="Characteristic"> The local GATT characteristic object
    ///   that requested the read operation. </param>
	/// <param name="Request"> The GATT read request object. </param>
	/// <remarks> This method is called when a remote GATT client requests
    ///   read from the characteristic. </remarks>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="CwclGattLocalCharacteristicReadRequest" />
	virtual void DoRead(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicReadRequest* const Request);
	/// <summary> Fires the <c>OnStarted</c> event. </summary>
	virtual void DoStarted();
	/// <summary> Fires the <c>OnStopped</c> event. </summary>
	virtual void DoStopped();
	/// <summary> Fires the <c>OnSubscribed</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that subscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void DoSubscribed(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	/// <summary> Fires the <c>OnUnsubscribed</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void DoUnsubscribed(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	/// <summary> Fires the <c>OnWrite</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that requested write. </param>
	/// <param name="Characteristic"> The local GATT characteristic object
	///   that requested the write operation. </param>
	/// <param name="Request"> The GATT characteristic write request
    ///   object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="CwclGattLocalCharacteristicWriteRequest" />
	virtual void DoWrite(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicWriteRequest* const Request);
	
	/* HAL methods. */
	
	/// <summary> Implements a driver specific code to initialize Bluetooth LE
	///   GATT Server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver specific code. </remarks>
	virtual int HalInitialize() = 0;
	/// <summary> Implements a driver specific code to uninitialize Bluetooth LE
	///   GATT Server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver specific code. </remarks>
	virtual int HalUninitialize() = 0;
	
	/// <summary> Creates a driver specific local GATT service
	///   object. </summary>
	/// <param name="Uuid"> The service's UUID. </param>
	/// <param name="Service"> If the function completed with success this
	///   parameter includes just create local GATT service object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver specific code. </remarks>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="CwclGattLocalService" />
	virtual int HalCreateService(const wclGattUuid& Uuid, CwclGattLocalService*& Service) = 0;
	/// <summary> Creates a driver specific GATT server client
	///   object. </summary>
	/// <param name="Address"> The client's address. </param>
	/// <returns> If the method completed with success the returning value is
	///   just created <see cref="CwclGattServerClient" /> object. If the method
	///   failed the returning value is <c>nil</c>. </returns>
	/// <remarks> A derived class must override this method to provide
	///   driver specific code. </remarks>
	/// <seealso cref="CwclGattServerClient" />
	virtual CwclGattServerClient* HalCreateClient(const __int64 Address) = 0;
	
public:
	/// <summary> Creates a new "virtual" GATT Server connection
	///   object. </summary>
	/// <param name="Radio"> The Radio object that owns the connection. </param>
	/// <remarks> <para> An application must never create this class directly.
	///   Instead of that an application must use upper-level methods and
	///   classes. </para>
	///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
	///   <see cref="wclECritical" /> exception raises. </para> </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <exception cref="wclECritical"></exception>
	CwclGattServerConnection(CwclBluetoothRadio* const Radio);
	/// <summary> Frees the GATT Server connection. </summary>
	virtual ~CwclGattServerConnection();
	
	/// <summary> Starts the Bluetooth LE GATT Server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers or on any other Windows platform with BlueSoleil
	///   Bluetooth drivers. </remarks>
	int Start();
	/// <summary> Stops the Bluetooth LE GATT Server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers or on any other Windows platform with BlueSoleil
	///   Bluetooth drivers. </remarks>
	int Stop();
	
	/// <summary> Creates new local GATT service and adds it to the services
	///   list. </summary>
	/// <param name="Uuid"> The service's UUID. </param>
	/// <param name="Service"> If the function completed with success this
	///   parameter receives a just created GATT local service object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="CwclGattLocalService" />
	int AddService(const wclGattUuid& Uuid, CwclGattLocalService*& Service);
	/// <summary> Clears the local services list. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int ClearServices();
	/// <summary> Deletes the service with given index. </summary>
	/// <param name="Index"> The service's index. The parameter must be in range
	///   between 0 and ServicesCount - 1. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int DeleteService(const size_t Index);
	
	/// <summary> Gets the GATT server state. </summary>
	/// <returns> <c>True</c> if the GATT server is running. </returns>
	bool GetActive() const;
	/// <summary> Gets the GATT server state. </summary>
	/// <value> <c>True</c> if the GATT server is running. </value>
	__declspec(property(get = GetActive)) bool Active;

	/// <summary> Gets the GATT server client by its index. </summary>
	/// <param name="Index"> The client's index. The parameter must be in range
	///   between 0 and ClientsCount - 1. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <returns> The GATT server client object. </returns>
	/// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclGattServerClient* GetClients(const size_t Index) const;
	/// <summary> Gets the GATT server client by its index. </summary>
	/// <value> The GATT server client object. </value>
	/// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetClients)) CwclGattServerClient* Clients[];

	/// <summary> Gets the clients count. </summary>
	/// <returns> The clients count. </returns>
	size_t GetClientsCount() const;
	/// <summary> Gets the clients count. </summary>
	/// <value> The clients count. </value>
	__declspec(property(get = GetClientsCount)) size_t ClientsCount;

	/// <summary> Gets the connection owner. </summary>
	/// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
	/// <value> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </value>
	/// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the local GATT service by its index. </summary>
	/// <param name="Index"> The service's index. The parameter must be in range
	///   between 0 and ServicesCount - 1. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <returns> The local GATT service object. </returns>
	/// <remarks> If server has not been initialized the
	///   <see cref="wclEGattServer" /> exception raises. </remarks>
	/// <seealso cref="CwclGattLocalService" />
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEGattServer"></exception>
	CwclGattLocalService* GetServices(const size_t Index) const;
	/// <summary> Gets the local GATT service by its index. </summary>
	/// <value> The local GATT service object. </value>
	/// <remarks> If server has not been initialized the
	///   <see cref="wclEGattServer" /> exception raises. </remarks>
	/// <seealso cref="CwclGattLocalService" />
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEGattServer"></exception>
	__declspec(property(get = GetServices)) CwclGattLocalService* Services[];

	/// <summary> Gets the services count. </summary>
	/// <returns> The services count. </returns>
	size_t GetServicesCount() const;
	/// <summary> Gets the services count. </summary>
	/// <value> The services count. </value>
	__declspec(property(get = GetServicesCount)) size_t ServicesCount;
	
	/// <summary> The event fires when a client connected to the
	///   server. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnClientConnected);
	/// <summary> The event fires when a client disconnected from
	///   the server. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnClientDisconnected);
	/// <summary> The event fires when the connection parameters changed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <remarks> <para> Once this event received an application can use the
	///   <c>GetConnectionParams</c> method to get the current connection
	///   parameters. </para>
	///   <para> This feature is supported with <c>Microsoft</c> Bluetooth drivers on
	///   <c>Windows 11</c> and above. </para> </remarks>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnConnectionParamsChanged);
	/// <summary> The event fires when the connection PHY changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
    /// <remarks> <para> Once this event received an application can use the
	///   <c>GetConnectionPhyInfo</c> method to get the current connection
	///   parameters. </para>
	///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
	///   drivers on <c>Windows 11</c> and above. </para> </remarks>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnConnectionPhyChanged);
	/// <summary> The event fires when maximum PDU size changed for the
    ///   connected client. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnMaxPduSizeChanged);
	/// <summary> The event fires when a maximum notification size of a
	///   subscribed client has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnNotificationSizeChanged);
	/// <summary> The event fires when a remote GATT client requests
	///   characteristic's data read. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   requested read. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <param name="Request"> The GATT read request object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="TwclGattLocalCharacteristicReadRequest" />
	wclGattLocalCharacteristicReadEvent(OnRead);
	/// <summary> The event fires when the Bluetooth LE GATT Server has been
	///   successfully started. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStarted);
	/// <summary> The event fires when the Bluetooth LE GATT Server has been
	///   stopped. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStopped);
	/// <summary> The event fires when a remote GATT client subscribes to the
	///   characteristic changes notifications or indications. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   subscribed or unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	wclGattLocalCharacteristicSubscribedClientsChangedEvent(OnSubscribed);
	/// <summary> The event fires when a remote GATT client unsubscribes from
	///   the characteristic changes notifications or indications. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   subscribed or unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	wclGattLocalCharacteristicSubscribedClientsChangedEvent(OnUnsubscribed);
	/// <summary> The event fires when a remote device writes data to the
	///   characteristic. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   requested write. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <param name="Request"> The GATT characteristic write request object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="TwclGattLocalCharacteristicWriteRequest" />
	wclGattLocalCharacteristicWriteEvent(OnWrite);
};

/// <summary> The "virtual" connection for the Bluetooth LE Beacon Watcher. </summary>
/// <remarks> An application must not create or use this class directly.
///   Instead of that an application must use high-level Bluetooth
///   components. </remarks>
/// <seealso cref="CwclCustomConnection" />
class CwclBluetoothLeBeaconWatcherConnection : public CwclCustomConnection
{
	DISABLE_COPY(CwclBluetoothLeBeaconWatcherConnection);
	
private:
	bool						FMonitoring;
	CwclBluetoothRadio*			FRadio;
	unsigned short				FScanInterval;
	wclBluetoothLeScanningMode	FScanningMode;
	unsigned short				FScanWindow;

	void ResetScanParams();

	/* Parsers. */

	void ParseEddystoneBeacons(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void ParseManufacturerRawFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short CompanyId,
		const wclBluetoothLeAdvertisementFrameRawData& Data);

protected:
    /* Internal methods. */
	
	/// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

	/* Event routines. */

	/// <summary> Fires the <c>OnAdvertisementAppearanceFrame</c>
	///   event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Appearance"> The Bluetooth LE device appearance
	///   value. </param>
	virtual void DoAdvertisementAppearanceFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short Appearance);
	/// <summary> Fires the <c>OnAdvertisementFrameInformation</c>
    ///   event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="Name"> The Bluetooth LE advertiser's name. </param>
    /// <param name="PacketType"> The Bluetooth LE advertisement data packet
    ///   type. </param>
    /// <param name="Flags"> The Bluetooth LE advertisement packet payload
    ///   flags. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementType" />
    /// <seealso cref="wclBluetoothLeAdvertisementFlags" />
    virtual void DoAdvertisementFrameInformation(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const tstring& Name, const wclBluetoothLeAdvertisementType PacketType,
		const wclBluetoothLeAdvertisementFlags& Flags);
	/// <summary> Fires the <c>OnAdvertisementExtFrameInformation</c>
	///   event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AddressType"> The Bluetooth LE address type. </param>
	/// <param name="TxPower"> The received transmit power of the
	///   advertisement. Ranges from -127 dBm to 20 dBm. -128 indicates
	///   "no value". </param>
	/// <param name="Flags"> The Bluetooth LE advertisement extended frame
	///   flags. </param>
	/// <seealso cref="wclBluetoothAddressType" />
	/// <seealso cref="wclBluetoothLeExtendedFrameFlags" />
	virtual void DoAdvertisementExtFrameInformation(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const wclBluetoothAddressType AddressType, const char TxPower,
		const wclBluetoothLeExtendedFrameFlags& Flags);
	/// <summary> Fires the <c>OnAdvertisementRawFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="DataType"> The frame's data type. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>NULL</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementRawFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned char DataType,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnAdvertisementReceived</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>nil</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementReceived(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService16DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService16DataFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService32DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService32DataFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned long Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService128DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService128DataFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const GUID& Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnServiceSol16Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol16Frame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short Uuid);
	/// <summary> Fires the <c>OnServiceSol32Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol32Frame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned long Uuid);
	/// <summary> Fires the <c>OnServiceSol128Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol128Frame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const GUID& Uuid);
	/// <summary> Fires the <c>OnAdvertisementTxPowerLevelFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxPower"> The TX power level in range from -127 to 128
	///   dBm. </param>
	virtual void DoAdvertisementTxPowerLevelFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxPower);
	/// <summary> Fires the <c>OnAdvertisementUuidFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The advertised UUID value. </param>
	virtual void DoAdvertisementUuidFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const GUID& Uuid);
	/// <summary> Fires the <c>OnAltBeaconFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Reserved"> A 1-byte value from 0x00 to 0xFF. Interpretation
	///   of this value is to be defined by the manufacturer and is to be
	///   evaluated based on the CompanyId value. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAltBeaconFrame(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);
	/// <summary> Fires the <c>OnEddystoneTlmFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AdvCnt"> The running count of advertisement frames of all
	///   types emitted by the beacon since power-up or reboot, useful for
	///   monitoring performance metrics that scale per broadcast frame.
	///   If this value is reset (e.g. on reboot), the current time field is
	///   also reset. </param>
	/// <param name="Batt"> The current battery charge in millivolts, expressed
	///   as 1 mV per bit. If not supported (for example in a USB-powered
	///   beacon) the value should be zeroed. </param>
	/// <param name="SecCnt"> The 0.1 second resolution counter that represents
	///   time since beacon power-up or reboot. If this value is reset (e.g. on
	///   a reboot), the AdvCnt count field is also reset. </param>
	/// <param name="Temp"> The beacon temperature in degrees Celsius sensed by
	///   the beacon. If not supported the value is -128 °C. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoEddystoneTlmFrame(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);
    /// <summary> Fires the <c>OnEddystoneUidFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
    ///   -100 dBm and +20 dBm at 1 dBm resolution measured at 0 meter
    ///   distance. </param>
    /// <param name="Uuid"> The Eddystone ID: 10 bytes - Namespace ID and 6
    ///   bytes - Instance ID. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    virtual void DoEddystoneUidFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
    /// <summary> Fires the <c>OnEddystoneUrlFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
    ///   -100 dBm and +20 dBm at 1 dBm resolution measured at 0 meter
    ///   distance. </param>
    /// <param name="Url"> The Eddystone URL. </param>
    virtual void DoEddystoneUrlFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const tstring& Url);
    /// <summary> Fires the <c>OnManufacturerRawFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
    ///   Bluetooth SIG Assigned Numbers. </param>
    /// <param name="Data"> The frame raw data. The value can be <c>NULL</c> if
    ///   there is no any data available in the frame. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    virtual void DoManufacturerRawFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short CompanyId,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnProximityBeaconFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoProximityBeaconFrame(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 wclBluetoothLeAdvertisementFrameRawData& Data);
	
    /// <summary> Fires the <c>OnStarted</c> event. </summary>
    virtual void DoStarted();
    /// <summary> Fires the <c>OnStopped</c> event. </summary>
    virtual void DoStopped();

    /* HAL methods. */

    /// <summary> Implements a hardware-dependent code to start Bluetooth LE
    ///   Beacon monitoring. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   a driver-dependent code. </remarks>
    virtual int HalStart() = 0;
    /// <summary> Implements a hardware-dependent code to stop Bluetooth LE
    ///   Beacon monitoring. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   a driver-dependent code. </remarks>
    virtual int HalStop() = 0;

public:
    /// <summary> Creates a new "virtual" Beacon Watcher connection
    ///   object. </summary>
    /// <param name="Radio"> The Radio object that owns the connection. </param>
    /// <remarks> <para> An application must never create this class directly.
    ///   Instead of that an application must use upper-level methods and
    ///   classes. </para>
    ///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
    ///   <see cref="wclECritical" /> exception raises. </para> </remarks>
    /// <seealso cref="CwclBluetoothRadio" />
    /// <exception cref="wclECritical"></exception>
    CwclBluetoothLeBeaconWatcherConnection(CwclBluetoothRadio* const Radio);
    /// <summary> Frees the Beacon Watcher. </summary>
    virtual ~CwclBluetoothLeBeaconWatcherConnection();

    /// <summary> Starts monitoring for Bluetooth LE Beacons. </summary>
	/// <param name="ScanningMode"> Specifies the Bluetooth LE scanning
	///   mode. </param>
	/// <param name="ScanInterval"> Specifies the Bluetooth LE scan in 0.625 ms
    ///   units. The value must be in range between
    ///   <see cref="WCL_BLE_MIN_SCAN_INTERVAL" /> and
    ///   <see cref="WCL_BLE_MAX_SCAN_INTERVAL" />. The default value is
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" />. </param>
	/// <param name="ScanWindow"> Specifies the Bluetooth LE scan window in
    ///   0.625 ms units. The value must be in range between
    ///   <see cref="WCL_BLE_MIN_SCAN_WINDOW" /> and
    ///   <see cref="WCL_BLE_MAX_SCAN_WINDOW" />. The default value is
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" />. The scan window must be
    ///   less or equal to <c>ScanInterval</c>. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers only. If the method returns error try to call this
	///   method with default scan parameters. </remarks>
	/// <seealso cref="wclBluetoothLeScanningMode" />
	/// <seealso cref="WCL_BLE_MIN_SCAN_WINDOW" />
    /// <seealso cref="WCL_BLE_MAX_SCAN_WINDOW" />
    /// <seealso cref="WCL_BLE_DEFAULT_SCAN_WINDOW" />
	int Start(const wclBluetoothLeScanningMode ScanningMode,
		const unsigned short ScanInterval, const unsigned short ScanWindow);
    /// <summary> Stops monitoring for Bluetooth LE Beacons. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
    ///   Bluetooth drivers only. </remarks>
    int Stop();

    /// <summary> Gets Beacon Monitoring state. </summary>
    /// <returns> <c>True</c> if the Beacon monitoring is running. </returns>
    bool GetMonitoring() const;
	/// <summary> Gets Beacon Monitoring state. </summary>
    /// <value> <c>True</c> if the Beacon monitoring is running. </value>
	__declspec(property(get = GetMonitoring)) bool Monitoring;

	/// <summary> Gets the connection owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the current scan interval value. </summary>
	/// <returns> The current scan interval. If the watcher is stopped the
	///   returning value is always <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" /> </returns>
    unsigned short GetScanInterval() const;
	/// <summary> Gets the current scan interval value. </summary>
	/// <value> The current scan interval. If the watcher is stopped the
	///   returning value is always <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" /> </value>
	__declspec(property(get = GetScanInterval)) unsigned short ScanInterval;

	/// <summary> Gets the current scanning mode. </summary>
	/// <returns> The Bluetooth LE scanning mode. </returns>
	/// <seealso cref="wclBluetoothLeScanningMode" />
	wclBluetoothLeScanningMode GetScanningMode() const;
	/// <summary> Gets the current scanning mode. </summary>
	/// <value> The Bluetooth LE scanning mode. </value>
	/// <seealso cref="wclBluetoothLeScanningMode" />
	__declspec(property(get = GetScanningMode)) wclBluetoothLeScanningMode ScanningMode;

	/// <summary> Gets the current scan window value. </summary>
    /// <returns> The current scan window. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" /> </returns>
    unsigned short GetScanWindow() const;
	/// <summary> Gets the current scan window value. </summary>
    /// <value> The current scan window. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" /> </value>
	__declspec(property(get = GetScanWindow)) unsigned short ScanWindow;

	/// <summary> The event fires when an appearance advertisement frame
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Appearance"> The Bluetooth LE device appearance
	///   value. </param>
    wclBluetoothLeAdvertisementAppearanceFrameEvent(OnAdvertisementAppearanceFrame);
	/// <summary> The event fires when new Bluetooth LE advertisement frame
    ///   has been received and provides the common basic information about
    ///   the frame. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Name"> The Bluetooth LE advertiser's name. </param>
	/// <param name="PacketType"> The Bluetooth LE advertisement data packet
	///   type. </param>
	/// <param name="Flags"> The Bluetooth LE advertisement packet payload
	///   flags. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementType" />
	/// <seealso cref="wclBluetoothLeAdvertisementFlags" />
    wclBluetoothLeAdvertisementFrameInformationEvent(OnAdvertisementFrameInformation);
	/// <summary> The event fires when new Bluetooth LE advertisement
	///   extended frame has been received and provides the common basic
	///   information about the frame. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AddressType"> The Bluetooth LE address type. </param>
	/// <param name="TxPower"> The received transmit power of the
	///   advertisement. Ranges from -127 dBm to 20 dBm. -128 indicates
	///   "no value". </param>
	/// <param name="Flags"> The Bluetooth LE advertisement extended frame
	///   flags. </param>
	/// <seealso cref="wclBluetoothAddressType" />
	/// <seealso cref="wclBluetoothLeExtendedFrameFlags" />
	wclBluetoothLeAdvertisementExtFrameInformationEvent(OnAdvertisementExtFrameInformation);
    /// <summary> The <c>OnAdvertisementRawFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="DataType"> The frame's data type. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>NULL</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeAdvertisementRawFrameEvent(OnAdvertisementRawFrame);
	/// <summary> The event fires when any Bluetooth LE advertisement frame
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>nil</c>. </param>
	/// <remarks> Unlike the <c>OnAdvertisementRawFrame</c> and the
	///   <c>OnManufacturerRawFrame</c> this even fires for any Bluetooth LE
	///   advertisement and contains unparsed raw frame data. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementReceivedEvent(OnAdvertisementReceived);
	/// <summary> The event fires when a Bluetooth LE 16 bit Service Data
	///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementService16DataFrameEvent(OnAdvertisementService16DataFrame);
	/// <summary> The event fires when a Bluetooth LE 32 bit Service Data
	///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bits service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementService32DataFrameEvent(OnAdvertisementService32DataFrame);
	/// <summary> The event fires when a Bluetooth LE 128 bit Service Data
	///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bits service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeAdvertisementService128DataFrameEvent(OnAdvertisementService128DataFrame);
	/// <summary> The event fires when a Bluetooth LE 16 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol16FrameEvent(OnAdvertisementServiceSol16Frame);
	/// <summary> The event fires when a Bluetooth LE 32 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol32FrameEvent(OnAdvertisementServiceSol32Frame);
	/// <summary> The event fires when a Bluetooth LE 128 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol128FrameEvent(OnAdvertisementServiceSol128Frame);
	/// <summary> The event fires when a TX power level advertisement frame
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxPower"> The TX power level in range from -127 to 128
	///   dBm. </param>
	wclBluetoothLeAdvertisementTxPowerLevelFrameEvent(OnAdvertisementTxPowerLevelFrame);
	/// <summary> The event fires when an UUID advertisement frame has been
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The advertised UUID value. </param>
	wclBluetoothLeAdvertisementUuidFrameEvent(OnAdvertisementUuidFrame);
	/// <summary> The event fires when a Bluetooth LE Alt beacon
    ///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Reserved"> A 1-byte value from 0x00 to 0xFF. Interpretation
	///   of this value is to be defined by the manufacturer and is to be
	///   evaluated based on the CompanyId value. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeAltBeaconFrameEvent(OnAltBeaconFrame);
	/// <summary> The <c>OnEddystoneTlmFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AdvCnt"> The running count of advertisement frames of all
	///   types emitted by the beacon since power-up or reboot, useful for
	///   monitoring performance metrics that scale per broadcast frame.
	///   If this value is reset (e.g. on reboot), the current time field is
	///   also reset. </param>
	/// <param name="Batt"> The current battery charge in millivolts, expressed as
	///   1 mV per bit. If not supported (for example in a USB-powered beacon) the
	///   value should be zeroed. </param>
	/// <param name="SecCnt"> The 0.1 second resolution counter that represents
	///   time since beacon power-up or reboot. If this value is reset (e.g. on
	///   a reboot), the AdvCnt count field is also reset. </param>
	/// <param name="Temp"> The beacon temperature in degrees Celsius sensed by
	///   the beacon. If not supported the value is -128 °C. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeEddystoneTlmFrameEvent(OnEddystoneTlmFrame);
	/// <summary> The <c>OnEddystoneUidFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
	///   distance. </param>
	/// <param name="Uuid"> The Eddystone ID: 10 bytes - Namespace ID and 6
	///   bytes - Instance ID. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeEddystoneUidFrameEvent(OnEddystoneUidFrame);
	/// <summary> The <c>OnEddystoneUrlFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
	///   distance. </param>
	/// <param name="Url"> The Eddystone URL. </param>
    wclBluetoothLeEddystoneUrlFrameEvent(OnEddystoneUrlFrame);
	/// <summary> The <c>OnManufacturerRawFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Data"> The frame raw data. The value can be <c>NULL</c> if
	///   there is no any data available in the frame. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeManufacturerRawFrameEvent(OnManufacturerRawFrame);
	/// <summary> The <c>OnProximityBeaconFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeProximityBeaconFrameEvent(OnProximityBeaconFrame);
	/// <summary> The event fires when the Bluetooth LE beacon monitoring
	///   started. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	wclNotifyEvent(OnStarted);
	/// <summary> The event fires when the Bluetooth LE beacon monitoring
	///   stopped. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	wclNotifyEvent(OnStopped);
};

/// <summary> The base class for Bluetooth LE advertisement. </summary>
class CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeAdvertisement);

private:
	RTL_CRITICAL_SECTION	FCS;

protected:
	/// <summary> Enters the advertisement data protection critical
	///   section. </summary>
	void Enter() const;
	/// <summary> Leaves the advertisement data protection critical
	///   section. </summary>
	void Leave() const;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	CwclBluetoothLeAdvertisement();
	/// <summary> Frees the object. </summary>
	virtual ~CwclBluetoothLeAdvertisement();

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const = 0;
};

/// <summary> The base class for Bluetooth LE advertisements that include
///   calibrated RSSI value. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLeTxRssiAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeTxRssiAdvertisement);
	
private:
	char	FTxRssi;

public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeTxRssiAdvertisement(const char TxRssi);
	
	/// <summary> Gets the calibrated RSSI value. </summary>
	/// <returns> The calibrated RSSI value in dBm. </returns>
	char GetTxRssi() const;
	/// <summary> Gets the calibrated RSSI value. </summary>
	/// <value> The calibrated RSSI value in dBm. </value>
	__declspec(property(get = GetTxRssi)) char TxRssi;
};

/// <summary> The base class for Bluetooth LE advertisements that include
///   IDs. </summary>
/// <seealso cref="CwclBluetoothLeTxRssiAdvertisement" />
class CwclBluetoothLeIdAdvertisement : public CwclBluetoothLeTxRssiAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeIdAdvertisement);
	
private:
	unsigned short	FMajor;
	unsigned short	FMinor;
	GUID			FUuid;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Major"> The major value. </param>
	/// <param name="Minor"> The minor value. </param>
	/// <param name="Uuid"> The UUID. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeIdAdvertisement(const char TxRssi, const unsigned short Major,
		const unsigned short Minor, const GUID& Uuid);

	/// <summary> Gets the major value. </summary>
	/// <returns> The major value. </returns>
	unsigned short GetMajor() const;
	/// <summary> Gets the major value. </summary>
	/// <value> The major value. </value>
	__declspec(property(get = GetMajor)) unsigned short Major;

	/// <summary> Gets the minor value. </summary>
	/// <returns> The minor value. </returns>
	unsigned short GetMinor() const;
	/// <summary> Gets the minor value. </summary>
	/// <value> The minor value. </value>
	__declspec(property(get = GetMinor)) unsigned short Minor;

	/// <summary> Gets the UUID. </summary>
	/// <returns> The UUID. </returns>
	GUID GetUuid() const;
	/// <summary> Gets the UUID. </summary>
	/// <value> The UUID. </value>
	__declspec(property(get = GetUuid)) GUID Uuid;
};

/// <summary> The Bluetooth LE iBeacon advertisement. </summary>
/// <seealso cref="CwclBluetoothLeIdAdvertisement" />
class CwclBluetoothLeiBeaconAdvertisement : public CwclBluetoothLeIdAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeiBeaconAdvertisement);
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Major"> The major value. </param>
	/// <param name="Minor"> The minor value. </param>
	/// <param name="Uuid"> The UUID. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeiBeaconAdvertisement(const char TxRssi, const unsigned short Major,
		const unsigned short Minor, const GUID& Uuid);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
};

/// <summary> The base class for Bluetooth LE advertisements that include
///   company (manufacturer) ID. </summary>
/// <seealso cref="CwclBluetoothLeIdAdvertisement" />
class CwclBluetoothLeCompanyIdAdvertisement : public CwclBluetoothLeIdAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeCompanyIdAdvertisement);
	
private:
	unsigned short	FCompanyId;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Major"> The major value. </param>
	/// <param name="Minor"> The minor value. </param>
	/// <param name="Uuid"> The UUID. </param>
	/// <param name="CompanyId"> The manufacturer ID as defined in the Bluetooth
	///   SIG Assigned Numbers. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeCompanyIdAdvertisement(const char TxRssi, const unsigned short Major,
		const unsigned short Minor, const GUID& Uuid, const unsigned short CompanyId);
	
	/// <summary> Gets the manufacturer ID. </summary>
	/// <returns> The manufacturer ID as defined in the Bluetooth SIG
	///   Assigned Numbers. </returns>
	unsigned short GetCompanyId() const;
	/// <summary> Gets the manufacturer ID. </summary>
	/// <value> The manufacturer ID as defined in the Bluetooth SIG
	///   Assigned Numbers. </value>
	__declspec(property(get = GetCompanyId)) unsigned short CompanyId;
};

/// <summary> The Bluetooth LE proximity beacon advertisement. </summary>
/// <seealso cref="CwclBluetoothLeCompanyIdAdvertisement" />
class CwclBluetoothLeProximityBeaconAdvertisement : public CwclBluetoothLeCompanyIdAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeProximityBeaconAdvertisement);
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Major"> The major value. </param>
	/// <param name="Minor"> The minor value. </param>
	/// <param name="Uuid"> The UUID. </param>
	/// <param name="CompanyId"> The manufacturer ID as defined in the Bluetooth
	///   SIG Assigned Numbers. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeProximityBeaconAdvertisement(const char TxRssi, const unsigned short Major,
		const unsigned short Minor, const GUID& Uuid, const unsigned short CompanyId);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
};

/// <summary> The Bluetooth LE Alt beacon advertisement. </summary>
/// <seealso cref="CwclBluetoothLeCompanyIdAdvertisement" />
class CwclBluetoothLeAltBeaconAdvertisement : public CwclBluetoothLeCompanyIdAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeAltBeaconAdvertisement);
	
private:
	unsigned char	FReserved;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Major"> The major value. </param>
	/// <param name="Minor"> The minor value. </param>
	/// <param name="Uuid"> The UUID. </param>
	/// <param name="CompanyId"> The manufacturer ID as defined in the Bluetooth
	///   SIG Assigned Numbers. </param>
	/// <param name="Reserved"> The beacon's manufacturer reserved
	///   value. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeAltBeaconAdvertisement(const char TxRssi, const unsigned short Major,
		const unsigned short Minor, const GUID& Uuid, const unsigned short CompanyId,
		const unsigned char Reserved);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the beacon's manufacturer reserved value. </summary>
	/// <returns> A 1-byte value from 0x00 to 0xFF. Interpretation of this value
	///   is to be defined by the manufacturer and is to be evaluated based on
	///   the <c>CompanyId</c> value. </returns>
	unsigned char GetReserved() const;
	/// <summary> Gets the beacon's manufacturer reserved value. </summary>
	/// <value> A 1-byte value from 0x00 to 0xFF. Interpretation of this value
	///   is to be defined by the manufacturer and is to be evaluated based on
	///   the <c>CompanyId</c> value. </value>
	__declspec(property(get = GetReserved)) unsigned char Reserved;
};

/// <summary> The Bluetooth LE Eddystone UID beacon advertisement. </summary>
/// <seealso cref="CwclBluetoothLeTxRssiAdvertisement" />
class CwclBluetoothLeEddystoneUidBeaconAdvertisement : public CwclBluetoothLeTxRssiAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeEddystoneUidBeaconAdvertisement);
	
private:
	GUID	FUuid;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeEddystoneUidBeaconAdvertisement(const char TxRssi, const GUID& Uuid);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the beacon's UUID. </summary>
	/// <returns> The beacon's UUID. </returns>
	GUID GetUuid() const;
	/// <summary> Gets the beacon's UUID. </summary>
	/// <value> The beacon's UUID. </value>
	__declspec(property(get = GetUuid)) GUID Uuid;
};

/// <summary> The Bluetooth LE Eddystone URL beacon advertisement. </summary>
/// <seealso cref="CwclBluetoothLeTxRssiAdvertisement" />
class CwclBluetoothLeEddystoneUrlBeaconAdvertisement : public CwclBluetoothLeTxRssiAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeEddystoneUrlBeaconAdvertisement);
	
private:
	tstring					FUrl;
	
	wclEddystoneEncodedUrl	FUrlEncoded;
	unsigned char			FUrlScheme;
	
	int ParseUrl(const tstring& Value);
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="TxRssi"> The calibrated RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Url"> The beacon's URL. </param>
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeEddystoneUrlBeaconAdvertisement(const char TxRssi,
		const tstring& Url);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the beacon's URL. </summary>
	/// <returns> The beacon's URL. </returns>
	tstring GetUrl() const;
	/// <summary> Gets the beacon's URL. </summary>
	/// <value> The beacon's URL. </value>
	__declspec(property(get = GetUrl)) tstring Url;
};

/// <summary> The Bluetooth LE 16 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLe16ServiceAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe16ServiceAdvertisement);
	
private:
	unsigned short	FUuid;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 16 bit service's UUID. </param>
	CwclBluetoothLe16ServiceAdvertisement(const unsigned short Uuid);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's UUID. </summary>
	/// <returns> The 16 bit UUID. </returns>
	unsigned short GetUuid() const;
	/// <summary> Gets the service's UUID. </summary>
	/// <value> The 16 bit UUID. </value>
	__declspec(property(get = GetUuid)) unsigned short Uuid;
};

/// <summary> The Bluetooth LE 32 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLe32ServiceAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe32ServiceAdvertisement);
	
private:
	unsigned long	FUuid;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 32 bit service's UUID. </param>
	CwclBluetoothLe32ServiceAdvertisement(const unsigned long Uuid);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's UUID. </summary>
	/// <returns> The 32 bit UUID. </returns>
	unsigned long GetUuid() const;
	/// <summary> Gets the service's UUID. </summary>
	/// <value> The 32 bit UUID. </value>
	__declspec(property(get = GetUuid)) unsigned long Uuid;
};

/// <summary> The Bluetooth LE 128 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLe128ServiceAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe128ServiceAdvertisement);
	
private:
	GUID	FUuid;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 128 bit service's UUID. </param>
	CwclBluetoothLe128ServiceAdvertisement(const GUID& Uuid);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's UUID. </summary>
	/// <returns> The 128 bit UUID. </returns>
	GUID GetUuid() const;
	/// <summary> Gets the service's UUID. </summary>
	/// <value> The 128 bit UUID. </value>
	__declspec(property(get = GetUuid)) GUID Uuid;
};

/// <summary> The Bluetooth LE 16 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLe16ServiceAdvertisement" />
class CwclBluetoothLe16ServiceDataAdvertisement : public CwclBluetoothLe16ServiceAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe16ServiceDataAdvertisement);
	
private:
	wclBluetoothLeAdvertisementFrameRawData	FData;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 16 bit service's UUID. </param>
	/// <param name="Data"> The service's data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLe16ServiceDataAdvertisement(const unsigned short Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's data. </summary>
	/// <returns> The service's data. </returns>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the service's data. </summary>
	/// <value> The service's data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;
};

/// <summary> The Bluetooth LE 32 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLe32ServiceAdvertisement" />
class CwclBluetoothLe32ServiceDataAdvertisement : public CwclBluetoothLe32ServiceAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe32ServiceDataAdvertisement);
	
private:
	wclBluetoothLeAdvertisementFrameRawData	FData;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 32 bit service's UUID. </param>
	/// <param name="Data"> The service's data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLe32ServiceDataAdvertisement(const unsigned long Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's data. </summary>
	/// <returns> The service's data. </returns>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the service's data. </summary>
	/// <value> The service's data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;
};

/// <summary> The Bluetooth LE 128 bit UUID service advertisement. </summary>
/// <seealso cref="CwclBluetoothLe32ServiceAdvertisement" />
class CwclBluetoothLe128ServiceDataAdvertisement : public CwclBluetoothLe128ServiceAdvertisement
{
	DISABLE_COPY(CwclBluetoothLe128ServiceDataAdvertisement);

private:
	wclBluetoothLeAdvertisementFrameRawData	FData;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Uuid"> The 128 bit service's UUID. </param>
	/// <param name="Data"> The service's data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLe128ServiceDataAdvertisement(const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the service's data. </summary>
	/// <returns> The service's data. </returns>
    /// <seealso cref="TwclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the service's data. </summary>
	/// <value> The service's data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;
};

/// <summary> The Bluetooth LE custom advertisement. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLeCustomAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeCustomAdvertisement);
	
private:
	wclBluetoothLeAdvertisementFrameRawData	FData;
	unsigned char							FDataType;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="DataType"> <para> The Bluetooth LE advertisement data type.
	///   This is one of the data type defined in the wclUUIDs. </para>
	///   <para> The following advertisement types <c>are reserved and
	///   are not allowed</c>: </para>
	///   <para> * Empty flags (LE_GAP_AD_TYPE_NONE [0x00]) </para>
	///   <para> * Flags (LE_GAP_AD_TYPE_FLAGS [0x01]) </para>
	///   <para> * Shortened Local Name
	///            (LE_GAP_AD_TYPE_LOCAL_NAME_SHORT [0x08]) </para>
	///   <para> * Complete Local Name
	///            (LE_GAP_AD_TYPE_LOCAL_NAME_COMPLETE [0x09]) </para>
	///   <para> * LE Bluetooth Device Address
	///            (LE_GAP_AD_TYPE_ADDRESS [0x1B]) </para>
	///   <para> * LE Role (LE_GAP_AD_TYPE_ROLE [0x1C]) </para>
	///   <para> * Manufacturer Specific Information
	///            (LE_GAP_AD_TYPE_MANUFACTURER [0xFF]) </para>
	///   <para> The following advertisement types <c>are system-reserved and
	///   are not allowed</c> if the advertisement is used with <c>Microsoft</c>
	///   Bluetooth driver: </para>
	///   <para> * Incomplete List of 16-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_16_MORE [0x02]) </para>
	///   <para> * Complete List of 16-bit Service Class UUIDs
	///          * (LE_GAP_AD_TYPE_SERVICES_16_ALL [0x03]) </para>
	///   <para> * Incomplete List of 32-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_32_MORE [0x04]) </para>
	///   <para> * Complete List of 32-bit Service Class UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_32_ALL [0x05]) </para>
	///   <para> * Incomplete List of 128-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_128_MORE [0x06]) </para>
	///   <para> * Complete List of 128-bit Service Class UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_128_ALL [0x07]) </para>
	///   <para> * TX Power Level (LE_GAP_AD_TYPE_TXPOWER [0x0A]) </para>
	///   <para> * Class of Device (LE_GAP_AD_TYPE_COD [0x0D]) </para>
	///   <para> * Simple Pairing Hash C192
	///            (LE_GAP_AD_TYPE_PAIRING_HASH_C [0x0E]) </para>
	///   <para> * Simple Pairing Randomizer R192
	///            (LE_GAP_AD_TYPE_PAIRING_RAND_R [0x0F]) </para>
	///   <para> * Security Manager TK Values
	///            (LE_GAP_AD_TYPE_DEVICE_ID [0x10]) </para>
	///   <para> * Security Manager Out-of-Band Flags
	///            (LE_GAP_AD_TYPE_SM_OOB_FLAGS [0x11]) </para>
	///   <para> * Slave Connection Interval Range
	///            (LE_GAP_AD_TYPE_CON_INTERVALS [0x12]) </para>
	///   <para> * Public Target Address
	///            (LE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS [0x17]) </para>
	///   <para> * Random Target Address
	///            (LE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS [0x18]) </para>
	///   <para> * Appearance (LE_GAP_AD_TYPE_APPEARANCE [0x19]) </para>
	///   <para> * Advertising Interval
	///            (LE_GAP_AD_TYPE_ADV_INTERVAL [0x1A]) </para>
	///   <para> * Simple Pairing Hash C256
	///            (LE_GAP_AD_TYPE_PAIRING_HASH_C_256 [0x1D]) </para>
	///   <para> * Simple Pairing Randomizer R256
	///            (LE_GAP_AD_TYPE_PAIRING_RAND_R_256 [0x1E]) </para>
	///   <para> * 3D Information Data
	///            (LE_GAP_AD_TYPE_3D_INFO [0x3D]) </para> </param>
	/// <param name="Data"> The Bluetooth LE advertisement raw data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeCustomAdvertisement(const unsigned char DataType,
		const wclBluetoothLeAdvertisementFrameRawData& Data);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the advertisement raw data. </summary>
	/// <returns> The Bluetooth LE advertisement raw data. </returns>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the advertisement raw data. </summary>
	/// <value> The Bluetooth LE advertisement raw data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;

	/// <summary> Gets the advertisement data type. </summary>
	/// <returns> The Bluetooth LE advertisement data type as defined in
	///   wclUUIDs. </returns>
	unsigned char GetDataType() const;
	/// <summary> Gets the advertisement data type. </summary>
	/// <value> The Bluetooth LE advertisement data type as defined in
	///   wclUUIDs. </value>
	__declspec(property(get = GetDataType)) unsigned char DataType;
};

/// <summary> The Bluetooth LE custom manufacturer specific
///   advertisement. </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLeManufacturerAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeManufacturerAdvertisement);
	
private:
	unsigned short							FCompanyId;
	wclBluetoothLeAdvertisementFrameRawData	FData;
	
public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="CompanyId"> The manufacturer company ID. </param>
	/// <param name="Data"> The Bluetooth LE advertisement raw data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeManufacturerAdvertisement(const unsigned short CompanyId,
		const wclBluetoothLeAdvertisementFrameRawData& Data);

	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the manufacturer company ID. </summary>
	/// <returns> The manufacturer company ID. </returns>
	unsigned short GetCompanyId() const;
	__declspec(property(get = GetCompanyId)) unsigned short CompanyId;

	/// <summary> Gets the advertisement raw data. </summary>
	/// <returns> The Bluetooth LE advertisement raw data. </returns>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the advertisement raw data. </summary>
	/// <value> The Bluetooth LE advertisement raw data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;
};

/// <summary> The Bluetooth LE custom raw advertisement. </summary>
/// <remarks> This class allows to build a Bluetooth LE advertisement from raw
///   data bytes stream. </remarks>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
class CwclBluetoothLeRawAdvertisement : public CwclBluetoothLeAdvertisement
{
	DISABLE_COPY(CwclBluetoothLeRawAdvertisement);

private:
    wclBluetoothLeAdvertisementFrameRawData	FData;
	
	unsigned char GetFramesCount(const wclBluetoothLeAdvertisementFrameRawData& Data) const;

public:
	/// <summary> Creates new Bluetooth LE advertisement object. </summary>
	/// <param name="Data"> The Bluetooth LE advertisement raw data. </param>
    /// <remarks> <para> The following advertisement data types <c>are reserved
	///   and are not allowed</c>: </para>
	///   <para> * Empty flags (LE_GAP_AD_TYPE_NONE [0x00]) </para>
	///   <para> * Flags (LE_GAP_AD_TYPE_FLAGS [0x01]) </para>
	///   <para> * Shortened Local Name
	///            (LE_GAP_AD_TYPE_LOCAL_NAME_SHORT [0x08]) </para>
	///   <para> * Complete Local Name
	///            (LE_GAP_AD_TYPE_LOCAL_NAME_COMPLETE [0x09]) </para>
	///   <para> * LE Bluetooth Device Address
	///            (LE_GAP_AD_TYPE_ADDRESS [0x1B]) </para>
	///   <para> * LE Role (LE_GAP_AD_TYPE_ROLE [0x1C]) </para>
	///   <para> * Incomplete List of 16-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_16_MORE [0x02]) </para>
	///   <para> * Complete List of 16-bit Service Class UUIDs
	///          * (LE_GAP_AD_TYPE_SERVICES_16_ALL [0x03]) </para>
	///   <para> * Incomplete List of 32-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_32_MORE [0x04]) </para>
	///   <para> * Complete List of 32-bit Service Class UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_32_ALL [0x05]) </para>
	///   <para> * Incomplete List of 128-bit Service UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_128_MORE [0x06]) </para>
	///   <para> * Complete List of 128-bit Service Class UUIDs
	///            (LE_GAP_AD_TYPE_SERVICES_128_ALL [0x07]) </para>
	///   <para> * TX Power Level (LE_GAP_AD_TYPE_TXPOWER [0x0A]) </para>
	///   <para> * Class of Device (LE_GAP_AD_TYPE_COD [0x0D]) </para>
	///   <para> * Simple Pairing Hash C192
	///            (LE_GAP_AD_TYPE_PAIRING_HASH_C [0x0E]) </para>
	///   <para> * Simple Pairing Randomizer R192
	///            (LE_GAP_AD_TYPE_PAIRING_RAND_R [0x0F]) </para>
	///   <para> * Security Manager TK Values
	///            (LE_GAP_AD_TYPE_DEVICE_ID [0x10]) </para>
	///   <para> * Security Manager Out-of-Band Flags
	///            (LE_GAP_AD_TYPE_SM_OOB_FLAGS [0x11]) </para>
	///   <para> * Slave Connection Interval Range
	///            (LE_GAP_AD_TYPE_CON_INTERVALS [0x12]) </para>
	///   <para> * Public Target Address
	///            (LE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS [0x17]) </para>
	///   <para> * Random Target Address
	///            (LE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS [0x18]) </para>
	///   <para> * Appearance (LE_GAP_AD_TYPE_APPEARANCE [0x19]) </para>
	///   <para> * Advertising Interval
	///            (LE_GAP_AD_TYPE_ADV_INTERVAL [0x1A]) </para>
	///   <para> * Simple Pairing Hash C256
	///            (LE_GAP_AD_TYPE_PAIRING_HASH_C_256 [0x1D]) </para>
	///   <para> * Simple Pairing Randomizer R256
	///            (LE_GAP_AD_TYPE_PAIRING_RAND_R_256 [0x1E]) </para>
	///   <para> * 3D Information Data
	///            (LE_GAP_AD_TYPE_3D_INFO [0x3D]) </para> </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeRawAdvertisement(const wclBluetoothLeAdvertisementFrameRawData& Data);
	
	/// <summary> Builds the Bluetooth LE advertisement frames array that
	///   contains raw data of the Bluetooth LE advertisement. </summary>
	/// <param name="Frames"> On output contains the Bluetooth LE advertisement
	///   frames array representing the current advertisement data. </param>
	/// <remarks> A derived class must override this method. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrames" />
	virtual void GetFrames(wclBluetoothLeAdvertisementFrames& Frames) const override;
	
	/// <summary> Gets the advertisement raw data. </summary>
	/// <returns> The Bluetooth LE advertisement raw data. </returns>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementFrameRawData GetData() const;
	/// <summary> Gets the advertisement raw data. </summary>
	/// <value> The Bluetooth LE advertisement raw data. </value>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	__declspec(property(get = GetData)) wclBluetoothLeAdvertisementFrameRawData Data;
};

/// <summary> The type represents a Bluetooth LE advertisements list, </summary>
/// <seealso cref="CwclBluetoothLeAdvertisement" />
typedef std::list<CwclBluetoothLeAdvertisement*>	WCL_BLE_ADV_LIST;

/// <summary> The virtual connection class enables Bluetooth LE
///   advertising feature. </summary>
/// <remarks> <para> The class provides methods to enable Bluetooth LE
///   advertising. </para>
///   <para> The feature is supported only on Windows 10 platform with
///   <c>Microsoft</c> Bluetooth drivers or on any Windows platform with
///   <c>BLED112</c> Bluetooth dongle. </para> </remarks>
/// <seealso cref="CwclCustomConnection" />
class CwclBluetoothLeAdvertiserConnection : public CwclCustomConnection
{
	DISABLE_COPY(CwclBluetoothLeAdvertiserConnection);
	
private:
	WCL_BLE_ADV_LIST*	FAdvertisements;
	bool				FAdvertising;
	unsigned short		FInterval;
	HANDLE				FMutex;
    CwclBluetoothRadio*	FRadio;

	/* Extended advertisement properties. */
	
	bool				FAnonymous;
	bool				FIncludeTxRssi;
	char				FPreferredTxRssi;
	bool				FUseExtendedAdvertisement;
	
	int CheckAdvertisements(const WCL_BLE_ADV_LIST* const Advertisements) const;

protected:
    /* Internal methods. */

    /// <summary> The method called when a new notification message
    ///   received. </summary>
    /// <param name="Message"> A <see cref="CwclMessage" /> object
    ///   represents a notification message. </param>
    /// <remarks> <para> This method is for internal use only. </para>
    ///   <para> If a derived class overrides this method it must always call
    ///   the inherited implementation first. </para> </remarks>
    /// <seealso cref="CwclMessage" />
    virtual void MessageReceived(const CwclMessage* const Message) override;

    /* Event routines. */
	
	/// <summary> Fires the <c>OnStarted</c> event. </summary>
    virtual void DoStarted();
    /// <summary> Fires the <c>OnStopped</c> event. </summary>
    virtual void DoStopped();

    /* HAL methods. */

    /// <summary> Implements a hardware-dependent code to start Bluetooth LE
    ///   advertising. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   a driver-dependent code. </remarks>
    virtual int HalStart() = 0;
    /// <summary> Implements a hardware-dependent code to stop Bluetooth LE
    ///   advertising. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> A derived class must override this method to provide
    ///   a driver-dependent code. </remarks>
    virtual int HalStop() = 0;

public:
    /// <summary> Creates a new "virtual" Bluetooth LE Advertising connection
    ///   object. </summary>
    /// <param name="Radio"> The Radio object that owns the connection. </param>
    /// <remarks> <para> An application must never create this class directly.
    ///   Instead of that an application must use upper-level methods and
    ///   classes. </para>
    ///   <para> If the <c>Radio</c> parameter is <c>NULL</c> the
    ///   <see cref="wclECritical" /> exception raises. </para> </remarks>
    /// <seealso cref="CwclBluetoothRadio" />
    /// <exception cref="wclECritical"></exception>
    CwclBluetoothLeAdvertiserConnection(CwclBluetoothRadio* const Radio);
    /// <summary> Frees the Bluetooth LE Advertiser. </summary>
    virtual ~CwclBluetoothLeAdvertiserConnection();

	/// <summary> Starts Bluetooth LE Advertising. </summary>
	/// <param name="Advertisements"> The Bluetooth LE Advertisements
    ///   list. </param>
	/// <param name="Interval"> An advertising interval in 0.625 ms
	///   units. The value must be in range between
	///   <see cref="WCL_BLE_MIN_ADVERTISING_INTERVAL" /> and
	///   <see cref="WCL_BLE_MAX_ADVERTISING_INTERVAL" />. The default value is
	///   <see cref="WCL_BLE_DEFAULT_ADVERTISING_INTERVAL" />. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
    ///   Bluetooth drivers only. </remarks>
	/// <seealso cref="WCL_BLE_ADV_LIST" />
	/// <seealso cref="WCL_BLE_MIN_ADVERTISING_INTERVAL" />
    /// <seealso cref="WCL_BLE_MAX_ADVERTISING_INTERVAL" />
    /// <seealso cref="WCL_BLE_DEFAULT_ADVERTISING_INTERVAL" />
    int Start(WCL_BLE_ADV_LIST* const Advertisements, const unsigned short Interval);
    /// <summary> Stops Bluetooth LE Advertising. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
    ///   Bluetooth drivers only. </remarks>
    int Stop();

	/// <summary> Gets the Bluetooth LE advertisements list. </summary>
	/// <returns> The Bluetooth LE advertisements list. </returns>
	/// <seealso cref="WCL_BLE_ADV_LIST" />
	WCL_BLE_ADV_LIST* GetAdvertisements() const;
	/// <summary> Gets the Bluetooth LE advertisements list. </summary>
	/// <value> The Bluetooth LE advertisements list. </value>
	/// <seealso cref="WCL_BLE_ADV_LIST" />
	__declspec(property(get = GetAdvertisements)) WCL_BLE_ADV_LIST* Advertisements;

    /// <summary> Gets advertising state. </summary>
    /// <returns> <c>True</c> if advertising is running. </returns>
    bool GetAdvertising() const;
	/// <summary> Gets advertising state. </summary>
    /// <value> <c>True</c> if advertising is running. </value>
	__declspec(property(get = GetAdvertising)) bool Advertising;

	/// <summary> Gets the advertising interval. </summary>
    /// <returns> The advertising interval in 0.625ms units. </returns>
    unsigned short GetInterval() const;
	/// <summary> Gets the advertising interval. </summary>
    /// <value> The advertising interval in 0.625ms units. </value>
	__declspec(property(get = GetInterval)) unsigned short Interval;

    /// <summary> Gets the connection owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Specifies whether or not the device address is included in the
	///   advertisement header. By default, the address is included. </summary>
	/// <returns> The value indicates whether the device address is hidden. </returns>
	bool GetAnonymous() const;
	/// <summary> Specifies whether or not the device address is included in the
	///   advertisement header. By default, the address is included. </summary>
	/// <param name="value"> Indicates whether the device address is hidden. The default
	///   value is <c>False</c>, indicating that the address is
	///   included. </param>
	/// <remarks> <para> The Extended Advertising format must be enabled by
	///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
	///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
	///   value of this property is ignored. </para>
	///   <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetAnonymous(const bool value);
	/// <summary> Specifies whether or not the device address is included in the
    ///   advertisement header. By default, the address is included. </summary>
    /// <value> Indicates whether the device address is hidden. The default
    ///   value is <c>False</c>, indicating that the address is
    ///   included. </value>
    /// <remarks> <para> The Extended Advertising format must be enabled by
    ///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
    ///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
    ///   value of this property is ignored. </para>
    ///   <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetAnonymous, put = SetAnonymous)) bool Anonymous;

	/// <summary> Specifies whether the transmit power level is included in
	///   the advertisement header. </summary>
	/// <returns> The value indicates whether the transmit power level is
	///   included. </returns>
	bool GetIncludeTxRssi() const;
	/// <summary> Specifies whether the transmit power level is included in
	///   the advertisement header. </summary>
	/// <param name="value"> Indicates whether the transmit power level is included.
	///   The default value is <c>False</c>. </param>
	/// <remarks> <para> The Extended Advertising format must be enabled by
	///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
	///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
	///   value of this property is ignored. </para>
	///   <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetIncludeTxRssi(const bool value);
	/// <summary> Specifies whether the transmit power level is included in
    ///   the advertisement header. </summary>
    /// <value> Indicates whether the transmit power level is included. The
    ///   default value is <c>False</c>. </value>
    /// <remarks> <para> The Extended Advertising format must be enabled by
    ///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
    ///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
    ///   value of this property is ignored. </para>
    ///   <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetIncludeTxRssi, put = SetIncludeTxRssi))
		bool IncludeTxRssi;

	/// <summary> If specified, requests that the radio use the indicated
	///   transmit power level for the advertisement. </summary>
	/// <returns> The requested power level in dDm at range between -100
	///   dBm and +20 for the radio transmission. </returns>
	char GetPreferredTxRssi() const;
	/// <summary> If specified, requests that the radio use the indicated
	///   transmit power level for the advertisement. </summary>
	/// <param name="value"> The requested power level in dDm at range between -100
	///   dBm and +20 for the radio transmission. The default is -127 indicating
	///   that this feature is disabled. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <remarks> <para> Enabling the Extended Advertising format is necessary
	///   to enable several other related properties. </para>
	///  <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetPreferredTxRssi(const char value);
	/// <summary> If specified, requests that the radio use the indicated
    ///   transmit power level for the advertisement. </summary>
    /// <value> The requested power level in dDm at range between -100
    ///   dBm and +20 for the radio transmission. The default is -127 indicating
    ///   that this feature is disabled. If the parameter is out of range the
    ///   <see cref="wclEInvalidArgument" /> exception raises. </value>
    /// <remarks> <para> Enabling the Extended Advertising format is necessary
    ///   to enable several other related properties. </para>
    ///  <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEInvalidArgument"></exception>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetPreferredTxRssi, put = SetPreferredTxRssi))
		char PreferredTxRssi;

	/// <summary> Specifies that the advertisement publisher should use the
	///   Extended Advertising format. </summary>
	/// <returns> The value indicates whether or not the Extended Advertising format
	///   should be used. </returns>
	bool GetUseExtendedAdvertisement() const;
	/// <summary> Specifies that the advertisement publisher should use the
	///   Extended Advertising format. </summary>
	/// <param name="value"> Indicates whether or not the Extended Advertising format
	///   should be used. The default value is <c>False</c>. </param>
	/// <remarks> <para> Enabling the Extended Advertising format is necessary
	///   to enable several other related properties. </para>
	///  <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetUseExtendedAdvertisement(const bool value);
	/// <summary> Specifies that the advertisement publisher should use the
    ///   Extended Advertising format. </summary>
    /// <value> Indicates whether or not the Extended Advertising format should
    ///   be used. The default value is <c>False</c>. </value>
    /// <remarks> <para> Enabling the Extended Advertising format is necessary
    ///   to enable several other related properties. </para>
    ///  <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetUseExtendedAdvertisement, put = SetUseExtendedAdvertisement))
		bool UseExtendedAdvertisement;

	/// <summary> The event fires when the Bluetooth LE advertising
    ///   started. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(OnStarted);
    /// <summary> The event fires when the Bluetooth LE advertising
    ///   stopped. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(OnStopped);
};

/// <summary> The virtual connection represents a Wii Remote
///   client. </summary>
/// <remarks> <para> The class provides methods to receive data from
///   the Wii Remote controller. </para>
///   <para> An application must never create instances of this class
///   directly. Instead of that an application must use related methods
///   from the <see cref="CwclBluetoothRadio" /> object. </para>
///   <para> The feature is supported only on Windows 10 platform with
///   Microsoft Bluetooth drivers. </para> </remarks>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="CwclClientConnection" />
class CwclWiiRemoteClientConnection : public CwclClientConnection
{
	DISABLE_COPY(CwclWiiRemoteClientConnection);
	
private:
	// Remote device address.
	__int64				FAddress;
	// Initialization indication.
	bool				FInitialized;
	// The owner.
	CwclBluetoothRadio*	FRadio;
	
	/* Event objects. */
	
	HANDLE	FDisconnectEvent;
	HANDLE	FReadMemoryEvent;
	HANDLE	FWriteMemoryEvent;
	
	/* Read memory buffers. */
	
	unsigned char*	FReadBuffer;
	unsigned short	FReadOffset;
	unsigned short	FReadSize;
	
	/* Calibration data. */
	
	wclWiiRemoteAccelCalibration				FAccelCalibration;
	wclWiiRemoteBalanceBoardCalibration			FBalanceBoardCalibration;
	wclWiiRemoteClassicControllerCalibration	FClassicControllerCalibration;
	wclWiiRemoteNunchukCalibration				FNunchukCalibration;
	
	/* States. */
	
	// Indicates if accelerometer is enabled.
	bool						FAccelEnabled;
	wclWiiRemoteExtension		FExtension;
	wclWiiRemoteIrMode			FIrMode;
	wclWiiRemoteIrSensitivity	FIrSensitivity;
	wclWiiRemoteLeds			FLeds;
	bool						FRumble;
	
	/* Helper functions. */
	
	int CheckInitialized();
	wclWiiRemoteExtension DecodeExtensionType(const unsigned char* const Report) const;
	double GetBalanceBoardSensorValue(const unsigned short Sensor, const unsigned short Min,
		const unsigned short Mid, const unsigned short Max) const;
	unsigned char GetReportId(const bool Accel, const bool Ir, const bool Ext) const;
	unsigned char GetRumbleBit() const;
	int Wait(const HANDLE Event) const;
	
	/* Read functions. */
	
	int ReadCalibration();
	int ReadMemory(const unsigned long Address, const unsigned short Size,
		unsigned char*& Data);
	
	/* Write functions. */
	
	int WriteMemory(const unsigned long Address, const unsigned char Size, const unsigned char* const Data);
	int WriteMemory(const unsigned long Address, const unsigned char Data);
	int WriteReport(const unsigned char* const Report, const unsigned char Size);
	
	/* IR control functions. */
	
	int DisableIr();
	int EnableIr();
	int EnableIr(const wclWiiRemoteIrMode Mode, const wclWiiRemoteIrSensitivity Sensitivity);
	int SetIrLevel1();
	int SetIrLevel2();
	int SetIrLevel3();
	int SetIrLevel4();
	int SetIrLevel5();
	int SetIrLevelMax();
	
	/* Report control functions. */
	
	int SetReportType(const unsigned char ReportType, const bool Continuous);
	int SetReportType(unsigned char ReportType, const wclWiiRemoteIrSensitivity Sensitivity,
		const bool Continuous);
	
	/* Initialization functions. */
	
	int InitializeBalanceBoard();
	int InitializeClassicController();
	int InitializeMusicExtensions();
	int InitializeNunchuk();
	
	int InitializeExtension();
	
	/* Report parsers. */
	
	void ParseBalanceBoardExtension(const unsigned char* const Report, const unsigned char Offset) const;
	void ParseClassicControllerExtension(const unsigned char* Report, const unsigned char Offset) const;
	void ParseDrumsExtension(const unsigned char* const Report, const unsigned char Offset) const;
	void ParseGuitarExtension(const unsigned char* const Report, const unsigned char Offset) const;
	void ParseNunchukExtension(const unsigned char* const Report, const unsigned char Offset) const;
	
	void ParseExtensions(const unsigned char* const Report, const unsigned char Offset) const;
	
	void ParseAccel(const unsigned char* const Report) const;
	void ParseButtons(const unsigned char* const Report) const;
	void ParseIr(const unsigned char* const Report) const;
	void ParseReadMemory(const unsigned char* const Report);
	void ParseStatus(const unsigned char* const Report);
	
	void ParseInputReport(const unsigned char* const Report);
	
	/* Cleanup. */
	
	void ResetCalibrations();
	void ResetExtensionCalibration();
	void ResetStates();
	
protected:
	/// <summary> The function parses the received report. </summary>
	/// <param name="Report"> A pointer to the report data. </param>
	/// <remarks> The method must be called from the communication thread
	///   to process received reports. </remarks>
	void ProcessReport(const unsigned char* const Report);
	
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message) override;
	
	/// <summary> Implements a hardware-dependent code that connects to a
	///   remote device. </summary>
	/// <param name="Event"> The system even object handle. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> Derived classes must override this method to implement
	///   a hardware-dependent code that connects to a remote device. </para>
	///   <para> The method executes in a separate thread. </para>
	///   <para> The method implementation must monitor the <c>Event</c>
	///   parameter. The <c>Event</c> parameter is set if the
	///   <c>Disconnect</c> method was called. If the termination event was set
	///   the method must terminate connection operation. </para>
	///   <para> If connection to a remote device was terminated the method
	///   must release all allocated resources because the <c>HalDisconnect</c>
	///   will not be called. </para>
	///   <para> A derived class must always call inherited
	///   method. </para> </remarks>
	virtual int HalConnect(const HANDLE Event) override;
	/// <summary> Implements a hardware-dependent code that disconnects from the
	///   connected remote device. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> The method is called only if a connection to a remote
	///   device was established with success (the <c>Connect</c> method was
	///   success). </para>
	///   <para> The method will not be called if the connection to the  remote
	///   device was terminated in the middle of the <c>HalConnect</c>
	///   method. </para>
	///   <para> A derived HalConnect implementation <c>must</c> always call
	///   the <c>HalConnect</c> method first, before any other connection
	///   operation. If the connection is failed the derived implementation
	///   <c>must</c> always call inherited <c>HalDisconnect</c> method. </para>
	///   <para> A derived class must always call inherited
	///   method. </para> </remarks>
	virtual int HalDisconnect() override;
	/// <summary> Implements a hardware-dependent code that writes data report
	///   to the connected Wii Remote controller. </summary>
	/// <param name="Report"> The pointer to the report data buffer. </param>
	/// <param name="Size"> The report data size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> A derived class must override this method to implement
	///   a hardware-dependent code that sends data to the connected device.
	///   The method executes in the main thread and must be
	///   synchronous. </para>
	///   <para> A derived implementation must always call this method in case
	///   of the derived <c>HalConnect</c> failed. </para> </remarks>
	virtual int HalWrite(const unsigned char* const Report, const unsigned char Size) = 0;
	
	/// <summary> Fire the <c>OnAccelChanged</c> event. </summary>
	/// <param name="Accel"> The current accelerometer data. </param>
	/// <seealso cref="wclWiiRemoteAccel" />
	virtual void DoAccelChanged(const wclWiiRemoteAccel& Accel);
	/// <summary> Fires the <c>OnBalanceBoardChanged</c> event </summary>
	/// <param name="Board"> The new Balance Board extension
	///   state. </param>
	/// <seealso cref="wclWiiRemoteBalanceBoard" />
	virtual void DoBalanceBoardChanged(const wclWiiRemoteBalanceBoard& Board);
	/// <summary> Fires the <c>OnButtonsChanged</c> event. </summary>
	/// <param name="Buttons"> The new buttons state. </param>
	/// <seealso cref="wclWiiRemoteButtons" />
	virtual void DoButtonsChanged(const wclWiiRemoteButtons& Buttons);
	/// <summary> Fires the <c>OnClassicControllerChanged</c> event. </summary>
	/// <param name="Controller"> The current state of the Wii Remote Classic
	///   Controller extension. </param>
	/// <seealso cref="wclWiiRemoteClassicController" />
	virtual void DoClassicControllerChanged(const wclWiiRemoteClassicController& Controller);
	/// <summary> Fires the <c>OnConnect</c> event. </summary>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
	virtual void DoConnect(const int Error);
	/// <summary> Fires the <c>OnDisconnect</c> event. </summary>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	virtual void DoDisconnect(const int Reason);
	/// <summary> Fires the <c>OnDrumsChanged</c> event. </summary>
	/// <param name="Drums"> The current state of the Drums extension. </param>
	/// <seealso cref="wclWiiRemoteDrums" />
	virtual void DoDrumsChanged(const wclWiiRemoteDrums& Drums);
	/// <summary> Fires the <c>OnExtensionAttached</c> event. </summary>
	virtual void DoExtensionAttached();
	/// <summary> Fires the <c>OnExtensionDetached</c> event. </summary>
	virtual void DoExtensionDetached();
	/// <summary> Fires the <c>OnGuitarChanged</c> event. </summary>
	/// <param name="Guitar"> The current Guitar extension state. </param>
	/// <seealso cref="wclWiiRemoteGuitar" />
	virtual void DoGuitarChanged(const wclWiiRemoteGuitar& Guitar);
	/// <summary> Fires the <c>OnIrChanged</c> event. </summary>
	/// <param name="Ir"> The IR sensor data. </param>
	/// <seealso cref="wclWiiRemoteIrSensors" />
	virtual void DoIrChanged(const wclWiiRemoteIrSensors& Ir);
	/// <summary> Fires the <c>OnNunchukChanged</c> event. </summary>
	/// <param name="Nunchuk"> The current Nunchuk extension state. </param>
	/// <seealso cref="wclWiiRemoteNunchuk" />
	virtual void DoNunchukChanged(const wclWiiRemoteNunchuk& Nunchuk);
	/// <summary> Fires the <c>OnStatusChanged</c> event. </summary>
	/// <param name="Batt"> The WeDo Remote battery level. </param>
	/// <param name="Leds"> The We Do Remote LEDs state. </param>
	/// <seealso cref="wclWiiRemoteLeds" />
	virtual void DoStatusChanged(const double Batt, const wclWiiRemoteLeds& Leds);
	
	/// <summary> Gets the disconnect event object. </summary>
	/// <returns> The disconnect event object. </returns>
	HANDLE GetDisconnectEvent() const;
	/// <summary> Gets the disconnect event object. </summary>
	/// <value> The disconnect event object. </value>
	__declspec(property(get = GetDisconnectEvent)) HANDLE DisconnectEvent;
	
public:
	/// <summary> Create new Wii Remote client connection. </summary>
	/// <param name="Radio"> The Radio object that owns the connection. </param>
	/// <remarks> <para> An application must never create this class directly.
	///   Instead of that an application must use upper-level methods and
	///   classes. </para>
	///   <para> If the <c>Radio</c> parameter is <c>nil</c> the
	///   <see cref="wclECritical" /> exception raises. </para> </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <exception cref="wclECritical"></exception>
	CwclWiiRemoteClientConnection(CwclBluetoothRadio* const Radio);
	
	/// <summary> Connects to a remote device. </summary>
	/// <param name="Address"> The remote Bluetooth device address. </param>
	/// <param name="Timeout"> The connect timeout in milliseconds. The
	///   default value is 10000 milliseconds. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> The method starts a connection operation to a remote
	///   device. If the method success that does not mean that the connection
	///   was established. That just means that the connection operation was
	///   started. The real connection result will be passed to the
	///   <c>OnConnect</c> event handler. </para>
	///   <para> NOTE: BlueSoleil does not support <c>Authentication</c>
	///   and <c>Encryption</c> parameters per connection. </para> </remarks>
	int Connect(const __int64 Address, const unsigned long Timeout = 10000);
	
	/// <summary> Requests the Wii Remote status. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This is asynchronous method. When operation completes the
	///   <c>OnStatusChanged</c> event fires. </remarks>
	int GetStatus();
	
	/// <summary> Changes the Wii Remote LEDs state. </summary>
	/// <param name="Leds"> The new LEDs state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclWiiRemoteLeds" />
	int SetLeds(const wclWiiRemoteLeds& Leds);
	/// <summary> Changes the Wii Remote LEDs state. </summary>
	/// <param name="Led1"> The new LED 1 state. </param>
	/// <param name="Led2"> The new LED 2 state. </param>
	/// <param name="Led3"> The new LED 3 state. </param>
	/// <param name="Led4"> The new LED 4 state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetLeds(const bool Led1, const bool Led2, const bool Led3, const bool Led4);
	/// <summary> Turns the Rumble On and Off. </summary>
	/// <param name="TurnOn"> Set to <c>True</c> to turn the Rumble On. Set
	///   to <c>False</c> to turn the Rumble Off. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetRumble(const bool TurnOn);
	
	/// <summary> Enables accelerometer. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int EnableAccel();
	/// <summary> Disables accelerometer. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int DisableAccel();
	
	/// <summary> Sets IR IR sensor sensitivity (and turns it ON or
	///   OFF). </summary>
	/// <param name="Sensitivity"> The IR sensor sensitivity. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	int SetIrSensitivity(const wclWiiRemoteIrSensitivity Sensitivity);
	
	/// <summary> Gets a remote device MAC address. </summary>
	/// <returns> The remote device MAC address. </returns>
	__int64 GetAddress() const;
	/// <summary> Gets a remote device MAC address. </summary>
	/// <value> The remote device MAC address. </value>
	__declspec(property(get = GetAddress)) __int64 Address;

	/// <summary> Gets the current accelerometer status. </summary>
	/// <returns> <c>True</c> if the accelerometer is enabled. <c>False</c>
	///   otherwise. </returns>
	bool GetAccelEnabled() const;
	/// <summary> Gets the current accelerometer status. </summary>
	/// <value> <c>True</c> if the accelerometer is enabled. <c>False</c>
	///   otherwise. </value>
	__declspec(property(get = GetAccelEnabled)) bool AccelEnabled;

	/// <summary> Gets the current connected extension type. </summary>
	/// <returns> The currently connected extension. </returns>
	/// <seealso cref="wclWiiRemoteExtension " />
	wclWiiRemoteExtension GetExtension() const;
	/// <summary> Gets the current connected extension type. </summary>
	/// <value> The currently connected extension. </value>
	/// <seealso cref="wclWiiRemoteExtension " />
	__declspec(property(get = GetExtension)) wclWiiRemoteExtension Extension;

	/// <summary> Gets the current IR sensor mode. </summary>
	/// <returns> The IR sensor mode. </returns>
	/// <seealso cref="wclWiiRemoteIrMode" />
	wclWiiRemoteIrMode GetIrMode() const;
	/// <summary> Gets the current IR sensor mode. </summary>
	/// <value> The IR sensor mode. </value>
	/// <seealso cref="wclWiiRemoteIrMode" />
	__declspec(property(get = GetIrMode)) wclWiiRemoteIrMode IrMode;

	/// <summary> Gets the current IR sensor sensitivity. </summary>
	/// <returns> The IR sensor sensitivity. </returns>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	wclWiiRemoteIrSensitivity GetIrSensitivity() const;
	/// <summary> Gets the current IR sensor sensitivity. </summary>
	/// <value> The IR sensor sensitivity. </value>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	__declspec(property(get = GetIrSensitivity)) wclWiiRemoteIrSensitivity IrSensitivity;

	/// <summary> Gets the current LEDs state. </summary>
	/// <returns> The LEDs state. </returns>
	/// <seealso cref="wclWiiRemoteLeds " />
	wclWiiRemoteLeds GetLeds() const;
	/// <summary> Gets the current LEDs state. </summary>
	/// <value> The LEDs state. </value>
	/// <seealso cref="wclWiiRemoteLeds " />
	__declspec(property(get = GetLeds)) wclWiiRemoteLeds Leds;

	/// <summary> Gets the connection owner. </summary>
	/// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection owner. </summary>
	/// <value> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </value>
	/// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the current Rumble status. </summary>
	/// <returns> <c>True</c> if the Rumble is turned ON. </returns>
	bool GetRumble() const;
	/// <summary> Gets the current Rumble status. </summary>
	/// <value> <c>True</c> if the Rumble is turned ON. </value>
	__declspec(property(get = GetRumble)) bool Rumble;

	/// <summary> The event fires when the accelerometer state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Accel"> The current accelerometer data. </param>
	/// <seealso cref="wclWiiRemoteAccel" />
	wclWiiRemoteAccelChangedEvent(OnAccelChanged);
	/// <summary> The event fires when the stat eof the Balance Board extension
	///   has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Board"> The new Balance Board extension
	///   state. </param>
	/// <seealso cref="wclWiiRemoteBalanceBoard" />
	wclWiiRemoteBalanceBoardChangedEvent(OnBalanceBoardChanged);
	/// <summary> The event fires when the buttons state of the Wii Remote
	///   controller has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Buttons"> The current state of the Wii Remote controller
	///   buttons. </param>
	/// <seealso cref="wclWiiRemoteButtons" />
	wclWiiRemoteButtonsChangedEvent(OnButtonsChanged);
	/// <summary> The event fires when a Classic Controller extension state has
	///   been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Controller"> The current state of the Wii Remote Classic
	///   Controller extension. </param>
	/// <seealso cref="wclWiiRemoteClassicController" />
	wclWiiRemoteClassicControllerChangedEvent(OnClassicControllerChanged);
	/// <summary> The event fires when the Drums extension state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Drums"> The current state of the Drums extension. </param>
	/// <seealso cref="wclWiiRemoteDrums" />
	wclWiiRemoteDrumsChangedEvent(OnDrumsChanged);
	/// <summary> The event fires when the extension is attached. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnExtensionAttached);
	/// <summary> The event fires when the extension has been
	///   detached. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnExtensionDetached);
	/// <summary> The event fires when the Guitar extension state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Guitar"> The current Guitar extension state. </param>
	/// <seealso cref="wclWiiRemoteGuitar" />
	wclWiiRemoteGuitarChangedEvent(OnGuitarChanged);
	/// <summary> The event fires when the IR sensor data has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Ir"> The IR sensor data. </param>
	/// <seealso cref="wclWiiRemoteIrSensors" />
	wclWiiRemoteIrChangedEvent(OnIrChanged);
	/// <summary> The event fires when the state of the Nunchuk extension has
	///   been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Nunchuk"> The current Nunchuk extension state. </param>
	/// <seealso cref="wclWiiRemoteNunchuk" />
	wclWiiRemoteNunchukChangedEvent(OnNunchukChanged);
	/// <summary> The event fires when the WeDo Remote status
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Batt"> The WeDo Remote battery level. </param>
	/// <param name="Leds"> The We Do Remote LEDs state. </param>
	/// <seealso cref="wclWiiRemoteLeds" />
	wclWiiRemoteStatusChangedEvent(OnStatusChanged);
};

/// <summary> The virtual connection represents a Wii Remote HID
///   client. </summary>
/// <remarks> <para> The class provides methods to receive data from
///   the Wii Remote controller. </para>
///   <para> An application must never create instances of this class
///   directly. Instead of that an application must use related methods
///   from the <see cref="CwclBluetoothRadio" /> object. </para>
///   <para> The feature is supported only on Windows 10 platform with
///   Microsoft Bluetooth drivers. </para> </remarks>
/// <seealso cref="CwclBluetoothRadio" />
/// <seealso cref="CwclWiiRemoteClientConnection" />
class CwclWiiRemoteHidClientConnection : public CwclWiiRemoteClientConnection
{
	DISABLE_COPY(CwclWiiRemoteHidClientConnection);
	
private:
	typedef std::list<tstring> WIIS;

	// HID device handle.
	HANDLE	FHandle;
	// Overlapped communication (read) event.
	HANDLE	FReadEvent;
	// Overlapped write event.
	HANDLE	FWriteEvent;
	// True of Wii Remote was paired by user.
	bool	FWasInstalled;
	
	// Enumerates installed (paired) Wii Remote devices.
	int EnumWiis(WIIS& Wiis);
	// Return device path for the Wii Remote with given MAC.
	int GetPath(tstring& Path);
	// Install Wii Remote device as HID one.
	int InstallDevice(const HANDLE Event, tstring& Path);
	// Removed Wii Remote device.
	int UninstallDevice();
	// Wait for timeout or disconnect.
	int CheckTimeout(const HANDLE Event, const DWORD Ticks);
	
	void TerminateIo(OVERLAPPED& Over);
	
	// Clears HID function pointers.
	void ClearHid();
	// Loads HID API.
	int LoadHid();
	// Unloads HID API.
	int UnloadHid();
	
protected:
	/// <summary> Connects to the Wii Remote as to HID device. </summary>
	/// <param name="Event"> The system even object handle. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int HalConnect(const HANDLE Event) override;
	/// <summary> Communicates with the Wii Remote as with HID
	///   device. </summary>
	/// <param name="Event"> The system even object handle (disconnect
	///   event). </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int HalCommunicate(const HANDLE Event) override;
	/// <summary> Disconnects from the Wii Remote as from HID device. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int HalDisconnect() override;
	/// <summary> Sends data to the Wii Remote as to HID device. </summary>
	/// <param name="Report"> The pointer to the report data buffer. </param>
	/// <param name="Size"> The report data size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	virtual int HalWrite(const unsigned char* const Report, const unsigned char Size) override;
	
public:
	/// <summary> Create new Wii Remote HID client connection. </summary>
	/// <param name="Radio"> The Radio object that owns the connection. </param>\
	/// <remarks> <para> An application must never create this class directly.
	///   Instead of that an application must use upper-level methods and
	///   classes. </para>
	///   <para> If the <c>Radio</c> parameter is <c>nil</c> the
	///   <see cref="wclECritical" /> exception raises. </para> </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <exception cref="wclECritical"></exception>
	CwclWiiRemoteHidClientConnection(CwclBluetoothRadio* const Radio);
};

/* Components */

/// <summary> The base class for all Bluetooth Components. </summary>
/// <remarks> The class implements the basic methods to prevent the
///   Bluetooth Connections from self-destruction. </remarks>
class CwclBluetoothComponent
{
	DISABLE_COPY(CwclBluetoothComponent);

private:
	CwclCustomConnection*	FCopy;
	RTL_CRITICAL_SECTION	FCS;

	void UnhookEvents();
	void DeleteCopy();
	
protected:
    /// <summary> The method sets new copy of the current connection. </summary>
    /// <param name="NewConnection"> The current connection used in Bluetooth
    ///   communication. </param>
    /// <seealso cref="CwclCustomConnection" />
	void SetCopy(CwclCustomConnection* const NewConnection);
	
	/// <summary> Enters the Bluetooth component protection critical
	///   section. </summary>
	void Enter() const;
	/// <summary> Leaves the Bluetooth component protection critical
	///   section. </summary>
	void Leave() const;
	
public:
    /// <summary> Creates a new component. </summary>
    CwclBluetoothComponent();
    /// <summary> Frees the component. </summary>
    virtual ~CwclBluetoothComponent();
};

/// <summary> The Bluetooth RFCOMM Client component. </summary>
/// <seealso cref="CwclBluetoothComponent" />
class CwclRfCommClient : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclRfCommClient);

private:
	__int64			FAddress;
    bool			FAuthentication;
    unsigned char	FChannel;
    bool			FEncryption;
    GUID			FService;
    unsigned long	FTimeout;

	bool							FActive;
    CwclRfCommClientConnection*		FClient;

	void ClientConnect(void* Sender, const int Error);
    void ClientData(void* Sender, const void* const Data, const unsigned long Size);
    void ClientDisconnect(void* Sender, const int Reason);

protected:
	/// <summary> Fires the <c>OnConnect</c> event. </summary>
    /// <param name="Error"> The connection operation result code. If the
    ///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
    ///   device was established and the remote device is connected. Otherwise
    ///   the connection was not established and the remote device is
    ///   not connected. </param>
    virtual void DoConnect(const int Error);
	/// <summary> Fires the <c>OnCreateProcessor</c> event. </summary>
    /// <param name="Connection"> The <see cref="CwclClientDataConnection" />
    ///   object that requires a data processor. </param>
    /// <seealso cref="CwclClientDataConnection" />
    virtual void DoCreateProcessor(CwclClientDataConnection* const Connection);
    /// <summary> Fires the <c>OnData</c> event. </summary>
    /// <param name="Data"> The pointer to the received data buffer.
    ///   It is guaranteed that the parameter points to a valid data buffer.
    ///   The data buffer is valid only inside the event handler. If an
    ///   application needs to use the data outside the event handle it must
    ///   allocate own buffer and copy data into it. </param>
    /// <param name="Size"> The data buffer size. It is guaranteed that the size
    ///   is greater than 0. </param>
    virtual void DoData(const void* const Data, const unsigned long Size);
	/// <summary> Fires the <c>OnDestroyProcessor</c> event. </summary>
    /// <param name="Connection"> The <see cref="CwclClientDataConnection" />
    ///   object that requires a data processor. </param>
    /// <seealso cref="CwclClientDataConnection" />
    virtual void DoDestroyProcessor(CwclClientDataConnection* const Connection);
    /// <summary> Fires the <c>OnDisconnect</c> event. </summary>
    /// <param name="Reason"> The disconnection code. If the
    ///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
    ///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
    ///   reason. </param>
    virtual void DoDisconnect(const int Reason);

public:
	/// <summary> Creates new RFCOMM client component. </summary>
	CwclRfCommClient();
	/// <summary> Frees the component. </summary>
	virtual ~CwclRfCommClient();

	/// <summary> Starts connecting to a remote Bluetooth device. </summary>
    /// <param name="Radio"> The <see cref="CwclBluetoothRadio" /> object
    ///   that handles the connection. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    int Connect(CwclBluetoothRadio* const Radio);
    /// <summary> Disconnects from the connection remote device. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int Disconnect();

	/// <summary> Reads the read buffer size. </summary>
    /// <param name="Size"> On output he read buffer size in bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetReadBufferSize(unsigned long& Size);
    /// <summary> Reads the write buffer size. </summary>
    /// <param name="Size"> On output the write buffer size in bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int GetWriteBufferSize(unsigned long& Size);

	/// <summary> Sets the read buffer size. </summary>
    /// <param name="Size"> The new read buffer size in bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int SetReadBufferSize(const unsigned long Size);
    /// <summary> Sets the write buffer size. </summary>
    /// <param name="Size"> The new write buffer size in bytes. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int SetWriteBufferSize(const unsigned long Size);

	/// <summary> Sends data to the connected device. </summary>
    /// <param name="Data"> The pointer to the data buffer that should be sent
    ///   to the connected device. </param>
    /// <param name="Size"> The data buffer size. </param>
    /// <param name="Written"> The amount of bytes actually written to the
    ///   device. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The write is synchronous operation. </remarks>
    int Write(const void* const Data, const unsigned long Size, unsigned long& Written);

	/// <summary> Gets the Data Processor created for the connection. </summary>
    /// <returns> The <see cref="CwclCustomClientDataProcessor" />
    ///   object. </returns>
    /// <seealso cref="CwclCustomClientDataProcessor" />
    CwclCustomClientDataProcessor* GetProcessor() const;
	/// <summary> Gets the Data Processor created for the connection. </summary>
    /// <value> The <see cref="CwclCustomClientDataProcessor" />
    ///   object. </value>
    /// <seealso cref="CwclCustomClientDataProcessor" />
	__declspec(property(get = GetProcessor)) CwclCustomClientDataProcessor* Processor;

	/// <summary> Gets the radio object used for connection. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the radio object used for connection. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the service's UUID that should be used
    ///   for connection. </summary>
    /// <returns> The Bluetooth service's UUID. </returns>
    GUID GetService() const;
    /// <summary> Sets the service's UUID that should be used
    ///   for connection. </summary>
    /// <param name="Value"> The Bluetooth service's UUID. </param>
    /// <remarks> If an application changes the property when connection is
    ///   active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    void SetService(const GUID& Value);
	/// <summary> Gets and sets the service's UUID that should be used
    ///   for connection. </summary>
    /// <value> The Bluetooth service's UUID. </value>
    /// <remarks> If an application changes the property when connection is
    ///   active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
	__declspec(property(get = GetService, put = SetService)) GUID Service;

    /// <summary> Gets the current client state. </summary>
    /// <returns> The client state. </returns>
    /// <seealso cref="wclClientState" />
    wclClientState GetState() const;
	/// <summary> Gets the current client state. </summary>
    /// <value> The client state. </value>
    /// <seealso cref="wclClientState" />
	__declspec(property(get = GetState)) wclClientState State;

	/// <summary> Gets a target Bluetooth device's MAC
    ///   address. </summary>
    /// <returns> The Bluetooth MAC address. </returns>
	__int64 GetAddress() const;
	/// <summary> Sets a target Bluetooth device's MAC
    ///   address. </summary>
	/// <param name="Value"> The Bluetooth MAC address. </param>
    /// <remarks> If an application changes the property when connection is
    ///   active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    void SetAddress(const __int64 Value);
	/// <summary> Gets and sets a target Bluetooth device's MAC
    ///   address. </summary>
    /// <value> The Bluetooth MAC address. </value>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
	__declspec(property(get = GetAddress, put = SetAddress)) __int64 Address;

	/// <summary> Gets the authentication property for the
    ///   connection. </summary>
    /// <returns> <c>True</c> if the authentication is enabled. </returns>
    bool GetAuthentication() const;
	/// <summary> Sets the authentication property for the
    ///   connection. </summary>
    /// <param name="Value"> <c>True</c> if the authentication is enabled. </param>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    void SetAuthentication(const bool Value);
	/// <summary> Gets and sets the authentication property for the
    ///   connection. </summary>
    /// <value> <c>True</c> if the authentication is enabled. </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
	__declspec(property(get = GetAuthentication, put = SetAuthentication))
		bool Authentication;

    /// <summary> Gets the RFCOMM channel number used for
    ///   connection. </summary>
    /// <returns> The RF COMM channel number. The value must be between 0 and 33
    ///   (including 0 and 32). </returns>
    unsigned char GetChannel() const;
	/// <summary> Sets the RFCOMM channel number used for
    ///   connection. </summary>
    /// <param name="Value"> The RF COMM channel number. The value must be between 0 and 33
    ///   (including 0 and 32). </param>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> If the <c>Channel</c> value is 0 a Bluetooth driver try to
    ///   resolve required channel number by querying a target devices SDP
    ///   using the service's UUID. In this case it will use the first found
    ///   service that matches the UUID. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
    void SetChannel(const unsigned char Value);
	/// <summary> Gets and sets the RFCOMM channel number used for
    ///   connection. </summary>
    /// <value> The RF COMM channel number. The value must be between 0 and 33
    ///   (including 0 and 32). </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> If the <c>Channel</c> value is 0 a Bluetooth driver try to
    ///   resolve required channel number by querying a target devices SDP
    ///   using the service's UUID. In this case it will use the first found
    ///   service that matches the UUID. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetChannel, put = SetChannel)) unsigned char Channel;

    /// <summary> Gets the Encryption property for the
    ///   connection. </summary>
    /// <returns> <c>True</c> if Encryption is enabled for the
    ///   connection. </returns>
    bool GetEncryption() const;
	/// <summary> Sets the Encryption property for the connection. </summary>
    /// <param name="Value"> <c>True</c> if Encryption is enabled for the
    ///   connection. </param>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> The Encryption can be turned on (<c>True</c>) only if
    ///   the <c>Authentication</c> property is also set to
    ///   <c>True</c>. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
    void SetEncryption(const bool Value);
	/// <summary> Gets and sets the Encryption property for the
    ///   connection. </summary>
    /// <value> <c>True</c> if Encryption is enabled for the
    ///   connection. </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </para>
    ///   <para> The Encryption can be turned on (<c>True</c>) only if
    ///   the <c>Authentication</c> property is also set to
    ///   <c>True</c>. </para> </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetEncryption, put = SetEncryption)) bool Encryption;

    /// <summary> Gets the connect timeout value. </summary>
    /// <returns> The connect timeout value in milliseconds. </returns>
    unsigned long GetTimeout() const;
	/// <summary> Sets the connect timeout value. </summary>
    /// <param name="Value"> The connect timeout value in milliseconds. </param>
    /// <remarks> If an application changes the property when client is
    ///   connected the <see cref="wclEClientActive" /> exception
    ///   raises. If new value of the <c>Timeout</c> is <c>0</c> the
    ///   <see cref="wclEInvalidArgument" /> exception raises. </remarks>
    /// <exception cref="wclEClientActive"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
    void SetTimeout(const unsigned long Value);
	/// <summary> Gets and sets the connect timeout value. </summary>
    /// <value> The connect timeout value in milliseconds. </value>
    /// <remarks> If an application changes the property when client is
    ///   connected the <see cref="wclEClientActive" /> exception
    ///   raises. If new value of the <c>Timeout</c> is <c>0</c> the
    ///   <see cref="wclEInvalidArgument" /> exception raises. </remarks>
    /// <exception cref="wclEClientActive"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetTimeout, put = SetTimeout)) unsigned long Timeout;

	/// <summary> The event fires when a connection to a remote device
    ///   has been completed (with or without success). </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
    /// <remarks> If the <c>Error</c> parameter of the event is not
    ///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
    ///   method again from inside the event handler. </remarks>
    wclClientConnectionConnectEvent(OnConnect);
	/// <summary> The event fires when connection to a remote device has
    ///   been established with success to allow application provide a
    ///   data processor for the connection. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The <see cref="CwclClientDataConnection" />
	///   object that requires a Data Processor. </param>
	/// <remarks> If an application needs an additional data processing it
    ///   can use Data Processors. An application must create a Data Processor
    ///   inside this event handler. If a Data Processor created for the
    ///   connection the <c>OnData</c> event will NOT fire. </remarks>
	/// <seealso cref="CwclClientDataConnection" />
	/// <seealso cref="CwclCustomClientDataProcessor" />
    wclClientConnectionProcessorEvent(OnCreateProcessor);
    /// <summary> The event fires when new data is received from the
    ///   connected remote device. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Data"> The pointer to the received data buffer.
	///   It is guaranteed that the parameter points to a valid data buffer.
	///   The data buffer is valid only inside the event handler. If an
	///   application needs to use the data outside the event handle it must
	///   allocate own buffer and copy data into it. </param>
	/// <param name="Size"> The data buffer size. It is guaranteed that the size
	///   is greater than 0. </param>
    wclConnectionDataEvent(OnData);
	/// <summary> The event fires when connection to a remote device has
    ///   been terminated. An application must destroy the Data Processor
    ///   created for the connection. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The <see cref="CwclClientDataConnection" />
	///   object that requires a Data Processor. </param>
    /// <seealso cref="CwclClientDataConnection" />
	/// <seealso cref="CwclCustomClientDataProcessor" />
    wclClientConnectionProcessorEvent(OnDestroyProcessor);
    /// <summary> The event fires when the remote connected device has been
    ///   disconnected. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
    wclClientConnectionDisconnectEvent(OnDisconnect);
};

/// <summary> Bluetooth RFCOMM server. </summary>
/// <remarks> The <c>TwclRfCommClient</c> component enables an
///   application to accept connections from Bluetooth devices through RFCOMM
///   protocol and work with RFCOMM based profiles (SPP, OBEX,
///   others). </remarks>
/// <seealso cref="CwclBluetoothComponent" />
class CwclRfCommServer : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclRfCommServer);

private:
    bool			FAuthentication;
    unsigned char	FChannel;
    bool			FEncryption;
    GUID			FService;
    tstring			FServiceName;

	bool						FActive;
    CwclRfCommServerConnection*	FServer;
    
    void ServerClosed(void* Sender, const int Reason);
    void ServerConnect(void* Sender, CwclServerClientConnection* const Client, const int Error);
    void ServerData(void* Sender, CwclServerClientDataConnection* const Client, const void* const Data,
		const unsigned long Size);
    void ServerDisconnect(void* Sender, CwclServerClientConnection* const Client, const int Reason);
    void ServerListen(void* Sender);
	void ServerGetSdpAttributes(void* Sender, wclBluetoothSdpProtocols& Protocols,
		wclBluetoothSdpProfiles& Profiles, wclBluetoothSdpFormats& Formats, unsigned long& Cod);

protected:
	/// <summary> Fires the <c>OnClosed</c> event. </summary>
    /// <param name="Reason"> Indicates closing reason. </param>
    virtual void DoClosed(const int Reason);
    /// <summary> Fires the <c>OnConnect</c> event. </summary>
    /// <param name="Client"> The
    ///   <see cref="CwclServerClientConnection" /> represents a remote
    ///   connected client. </param>
    /// <param name="Error"> The connection operation result code. If the
    ///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
    ///   device was established and the remote device is connected. Otherwise
    ///   the connection was not established and the remote device is
    ///   not connected. </param>
    /// <seealso cref="CwclRfCommServerClientConnection" />
    virtual void DoConnect(CwclRfCommServerClientConnection* const Client, const int Error);
	/// <summary> Fires the <c>OnCreateProcessor</c> event. </summary>
	/// <param name="Connection"> The
	///   <see cref="CwclServerClientDataConnection" /> object that requires a
	///   data processor. </param>
	/// <seealso cref="CwclServerClientDataConnection" />
	virtual void DoCreateProcessor(CwclServerClientDataConnection* const Connection);
    /// <summary> Fires the <c>OnData</c> event. </summary>
    /// <param name="Client"> A
    ///   <see cref="CwclRfCommServerClientConnection" /> object
    ///   represents a remote client connection. </param>
    /// <param name="Data"> The pointer to the received data buffer.
    ///   It is guaranteed that the parameter points to a valid data buffer.
    ///   The data buffer is valid only inside the event handler. If an
    ///   application needs to use the data outside the event handle it must
    ///   allocate own buffer and copy data into it. </param>
    /// <param name="Size"> The data buffer size. It is guaranteed that the size
    ///   is greater than 0. </param>
    /// <seealso cref="CwclRfCommServerClientConnection" />
    virtual void DoData(CwclRfCommServerClientConnection* const Client, const void* const Data,
		const unsigned long Size);
	/// <summary> Fires the <c>OnDestroyProcessor</c> event. </summary>
	/// <param name="Connection"> The
	///   <see cref="CwclServerClientDataConnection" /> object that requires a
	///   data processor. </param>
	/// <seealso cref="CwclServerClientDataConnection" />
	virtual void DoDestroyProcessor(CwclServerClientDataConnection* const Connection);
    /// <summary> Fires the <c>OnDisconnect</c> event. </summary>
    /// <param name="Client"> The
    ///   <see cref="CwclServerClientConnection" /> represents a remote
    ///   connected client. </param>
    /// <param name="Reason"> The disconnection code. If the
    ///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
    ///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
    ///   reason. </param>
    /// <seealso cref="CwclRfCommServerClientConnection" />
    virtual void DoDisconnect(CwclRfCommServerClientConnection* const Client, const int Reason);
    /// <summary> Fires the <c>OnListen</c> event. </summary>
    virtual void DoListen();
	/// <summary> Fires the <c>GetSdpAttributes</c> event. </summary>
    /// <param name="Protocols"> The additional protocol descriptors array that
    ///   should be added to SDP record. </param>
    /// <param name="Profiles"> The profile list that should be added to SDP
    ///   record. </param>
    /// <param name="Formats"> Other attributes that should be added to SDP
    ///   record. </param>
    /// <param name="Cod"> <para> Class of device (COD) information. A 32-bit
    ///   parameter of COD_SERVICE_* class of device bits associated with this
    ///   SDP record. The system combines these bits with COD bits from other
    ///   service records and system characteristics. The resulting class of
    ///   device for the local radio is advertised when the radio is found during
    ///   device inquiry. When the last SDP record associated with a particular
    ///   service bit is deleted, that service bit is no longer reported in
    ///   responses to future device inquiries. </para>
    ///   <para> The format and possible values for the COD field are defined in
    ///   the Bluetooth Assigned Numbers 1.1 portion of the Bluetooth
    ///   specification, Section 1.2. (This resource may not be available in some
    ///   languages and countries.) </para> </param>
    /// <remarks> <para> The HAL Radio implementation calls this method when
    ///   needs to add custom attributes into the SDP record. </para>
    ///   <para> BlueSoleil driver does not support custom SDP records and this
    ///   method does not work with BlueSoleil Bluetooth driver. </para>
    ///   <para> A derived class must always call the inherited
    ///   method.  </para> </remarks>
    /// <seealso cref="wclBluetoothSdpProtocols" />
    /// <seealso cref="wclBluetoothSdpProfiles" />
    /// <seealso cref="wclBluetoothSdpFormats" />
	virtual void DoGetSdpAttributes(wclBluetoothSdpProtocols& Protocols, wclBluetoothSdpProfiles& Profiles,
		wclBluetoothSdpFormats& Formats, unsigned long& Cod);

public:
    /// <summary> Creates a new component. </summary>
    CwclRfCommServer();
    /// <summary> Frees the component. </summary>
    virtual ~CwclRfCommServer();

    /// <summary> Closes the server. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int Close();
    /// <summary> The method starts listening for client connections. </summary>
    /// <param name="Radio"> The Bluetooth Radio that should handle the
    ///   connection. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="CwclBluetoothRadio"/>
    int Listen(CwclBluetoothRadio* const Radio);

    /// <summary> Gets the RFCOMM assigned channel number. </summary>
    /// <returns> The RFCOMM assigned channel number. </returns>
    unsigned char GetAssignedChannel() const;
	/// <summary> Gets the RFCOMM assigned channel number. </summary>
    /// <value> The RFCOMM assigned channel number. </value>
	__declspec(property(get = GetAssignedChannel)) unsigned char AssignedChannel;

    /// <summary> Gets the number of the connected clients. </summary>
    /// <returns> The number of the connected clients. </returns>
    size_t GetCount() const;
	/// <summary> Gets the number of the connected clients. </summary>
    /// <value> The number of the connected clients. </value>
	__declspec(property(get = GetCount)) size_t Count;

    /// <summary> Gets the connected client by its index. </summary>
    /// <returns> The <see cref="CwclRfCommServerClientConnection" /> represents
    ///   the connected client. </returns>
    /// <seealso cref="CwclRfCommServerClientConnection" />
    CwclRfCommServerClientConnection* GetClients(const size_t Index) const;
	/// <summary> Gets the connected client by its index. </summary>
    /// <value> The <see cref="CwclRfCommServerClientConnection" /> represents
    ///   the connected client. </value>
    /// <seealso cref="CwclRfCommServerClientConnection" />
	__declspec(property(get = GetClients)) CwclRfCommServerClientConnection* Clients[];

    /// <summary> Gets the connection radio object. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object that handles
    ///   the connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the connection radio object. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object that handles
    ///   the connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;
    
	/// <summary> Gets the Bluetooth service UUID used for
    ///   connection. </summary>
    /// <returns> A Bluetooth service UUID. </returns>
    GUID GetService() const;
	/// <summary> Sets the Bluetooth service UUID used for
    ///   connection. </summary>
    /// <param name="Value"> A Bluetooth service UUID. </param>
	/// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    void SetService(const GUID& Value);
	/// <summary> Gets and sets the Bluetooth service UUID used for
    ///   connection. </summary>
    /// <value> A Bluetooth service UUID. </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
	__declspec(property(get = GetService, put = SetService)) GUID Service;

    /// <summary> Gets the current connection state. </summary>
    /// <returns> The client connection state. </returns>
    /// <seealso cref="wclServerState" />
    wclServerState GetState() const;
	/// <summary> Gets the current connection state. </summary>
    /// <value> The client connection state. </value>
    /// <seealso cref="wclServerState" />
	__declspec(property(get = GetState)) wclServerState State;

    /// <summary> Gets the authentication value. </summary>
    /// <returns> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </returns>
    bool GetAuthentication() const;
	/// <summary> Sets the authentication value. </summary>
    /// <param name="Value"> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </param>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    void SetAuthentication(const bool Value);
	/// <summary> Gets and sets the authentication value. </summary>
    /// <value> <c>True</c> if the connection required authentication.
    ///   <c>False</c> otherwise. </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> If the Authentication if switched off (<c>False</c>) the
    ///   <c>Encryption</c> is also switched off. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
	__declspec(property(get = GetAuthentication, put = SetAuthentication))
		bool Authentication;

    /// <summary> Gets the service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <returns> The RFCOMM channel number used for connection. </returns>
    unsigned char GetChannel() const;
	/// <summary> Sets the service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <param name="Value"> The RFCOMM channel number used for connection. </param>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
    void SetChannel(const unsigned char Value);
	/// <summary> Gets and sets the service RFCOMM channel number. <c>0</c> to
    ///   auto detection. </summary>
    /// <value> The RFCOMM channel number used for connection. </value>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetChannel, put = SetChannel)) unsigned char Channel;

    /// <summary> Gets the encryption state of the connection. </summary>
    /// <returns> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </returns>
    bool GetEncryption() const;
	/// <summary> Sets the encryption state of the connection. </summary>
    /// <param name="Value"> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </param>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> The Encryption can be turned on (<c>True</c>) only if
    ///   the <c>Authentication</c> property is also set to
    ///   <c>True</c>. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
    void SetEncryption(const bool Value);
	/// <summary> Gets and sets the encryption state of the
    ///   connection. </summary>
    /// <value> <c>True</c> if the connection is encrypted. <c>False</c>
    ///   otherwise. </value>
    /// <remarks> <para> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </para>
    ///   <para> The Encryption can be turned on (<c>True</c>) only if
    ///   the <c>Authentication</c> property is also set to
    ///   <c>True</c>. </para> </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetEncryption, put = SetEncryption)) bool Encryption;

    /// <summary> Gets the service name. </summary>
    /// <returns> The service name. </returns>
    tstring GetServiceName() const;
	/// <summary> Sets the service name. </summary>
    /// <param name="Value"> The service name. </param>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
    void SetServiceName(const tstring& Value);
	/// <summary> Gets and sets the service name. </summary>
    /// <value> The service name. </value>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothServer" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothServer"></exception>
	__declspec(property(get = GetServiceName, put = SetServiceName))
		tstring ServiceName;

	/// <summary> The event fires when the server builds SDP record for
    ///   the service it runs. If an application needs to provide
    ///   additional attributes it should handle the event. By default no
    ///   additional attributes is added for the SDP record. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Protocols"> The additional protocol descriptors array that
	///   should be added to SDP record. </param>
	/// <param name="Profiles"> The profile descriptors list that should be added
	///   to SDP record. </param>
	/// <param name="Formats"> Other attributes that should be added to SDP
	///   record. </param>
	/// <param name="Cod"> <para> Class of device (COD) information. A 32-bit
	///   parameter of COD_SERVICE_* class of device bits associated with this
	///   SDP record. The system combines these bits with COD bits from other
	///   service records and system characteristics. The resulting class of
	///   device for the local radio is advertised when the radio is found during
	///   device inquiry. When the last SDP record associated with a particular
	///   service bit is deleted, that service bit is no longer reported in
	///   responses to future device inquiries. </para>
	///   <para> The format and possible values for the COD value are defined in
	///   the Bluetooth Assigned Numbers 1.1 portion of the Bluetooth
	///   specification, Section 1.2. (This resource may not be available in some
	///   languages and countries.) </para> </param>
    /// <remarks> This event will not fire with BlueSoleil Bluetooth
    ///   driver. BlueSoleil does not support custom SDP records. </remarks>
	/// <seealso cref="wclBluetoothSdpProtocols" />
	/// <seealso cref="wclBluetoothSdpProfiles" />
	/// <seealso cref="wclBluetoothSdpFormats" />
	wclBluetoothGetSdpAttributesEvent(GetSdpAttributes);
    /// <summary> The event fires when the server is closed. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
    wclClientConnectionDisconnectEvent(OnClosed);
    /// <summary> The event fires when a remote client is connected to
    ///   the server. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> The
	///   <see cref="CwclRfCommServerClientConnection" /> represents a remote
	///   connected client. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
	/// <seealso cref="CwclRfCommServerClientConnection" />
    wclRfCommServerConnectEvent(OnConnect);
	/// <summary> The event fires when connection to a remote device has
	///   been established with success to allow application provide a
	///   data processor for the connection. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The
	///   <see cref="CwclServerClientDataConnection" /> object that requires a
	///   Data Processor. </param>
	/// <remarks> If an application needs an additional data processing it
	///   can use Data Processors. An application must create a Data Processor
	///   inside this event handler. If a Data Processor created for the
	///   connection the <c>OnData</c> event will NOT fire. </remarks>
	/// <seealso cref="CwclCustomServerClientDataProcessor" />
	/// <seealso cref="CwclServerDataConnection" />
	/// <seealso cref="CwclServerClientDataConnection" />
	wclServerConnectionProcessorEvent(OnCreateProcessor);
    /// <summary> The event fires when new data is received from the
    ///   connected remote device. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> A
	///   <see cref="CwclRfCommServerClientConnection" /> object
	///   represents a remote client connection. </param>
	/// <param name="Data"> The pointer to the received data buffer.
	///   It is guaranteed that the parameter points to a valid data buffer.
	///   The data buffer is valid only inside the event handler. If an
	///   application needs to use the data outside the event handle it must
	///   allocate own buffer and copy data into it. </param>
	/// <param name="Size"> The data buffer size. It is guaranteed that the size
	///   is greater than 0. </param>
	/// <seealso cref="CwclRfCommServerClientConnection" />
    wclRfCommServerDataEvent(OnData);
	/// <summary> The event fires when connection to a remote device has
	///   been terminated. An application must destroy the Data Processor
	///   created for the connection. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The
	///   <see cref="CwclServerClientDataConnection" /> object that requires a
	///   Data Processor. </param>
	/// <seealso cref="CwclCustomServerClientDataProcessor" />
	/// <seealso cref="CwclServerDataConnection" />
	/// <seealso cref="CwclServerClientDataConnection" />
	wclServerConnectionProcessorEvent(OnDestroyProcessor);
    /// <summary> The event fires when a remote client has disconnected from the
    ///   server. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> The
	///   <see cref="CwclRfCommServerClientConnection" /> represents a remote
	///   connected client. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	/// <seealso cref="CwclRfCommServerClientConnection" />
    wclRfCommServerDisconnectEvent(OnDisconnect);
    /// <summary> The event fires when the server is ready to accept incoming
    ///   connections (is in listening state). </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(OnListen);
};

/// <summary> Bluetooth Low Energy GATT client. </summary>
/// <remarks> The <c>TwclGattClient</c> component enables an
///   application to connect to a Bluetooth Low Energy device and work
///   with GATT profiles. </remarks>
/// <seealso cref="CwclBluetoothComponent" />
class CwclGattClient : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclGattClient);

private:
    __int64	FAddress;
	bool	FConnectOnRead;
	bool	FForceNotifications;

	bool						FActive;
    CwclGattClientConnection*	FClient;

	int CheckSubscriptionMethod(const wclGattSubscribeKind SubscribeKind,
		wclGattCharacteristic& Characteristic);
	bool CompareUuid(const wclGattUuid& u1, const wclGattUuid& u2);
    
    // Client events.
    void ClientCharacteristicChanged(void* Sender, const unsigned short Handle,
		const unsigned char* const Value, const unsigned long Length);
    void ClientConnect(void* Sender, const int Error);
	void ClientConnectionParamsChanged(void* Sender);
	void ClientConnectionPhyChanged(void* Sender);
    void ClientDisconnect(void* Sender, const int Reason);
	void ClientMaxPduSizeChanged(void* Sender);

protected:
	/// <summary> Fires the <c>OnCharacteristicChanged</c> event. </summary>
    /// <param name="Handle"> A changed characteristic handle. </param>
    /// <param name="Value"> A pointer to the characteristic value. </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
    /// <remarks> The <c>Value</c> parameter is valid only inside the event
    ///   handler. If an application needs to use it outside the event handler
    ///   it must be copied. </remarks>
    virtual void DoCharacteristicChanged(const unsigned short Handle,
		const unsigned char* const Value, const unsigned long Length);
	/// <summary> Fires the <c>OnConnectionParamsChanged</c> event. </summary>
	virtual void DoConnectionParamsChanged();
	/// <summary> Fires the <c>OnConnectionPhyChanged</c> event. </summary>
    virtual void DoConnectionPhyChanged();
	/// <summary> Fires the <c>OnMaxPduSizeChanged</c> event. </summary>
    virtual void DoMaxPduSizeChanged();

    /// <summary> Fires the <c>OnConnected</c> event. </summary>
    /// <param name="Error"> The operation result. </param>
    virtual void DoConnect(const int Error);
    /// <summary> Fires then <c>OnDisconnected</c> event. </summary>
    virtual void DoDisconnect(const int Reason);

public:
    /// <summary> Creates new <c>TwclGattClient</c>
    ///   component. </summary>
    CwclGattClient();
    /// <summary> Frees the component. </summary>
    /// <remarks> The component must always be destroyed in the same thread it
    ///   was created. </remarks>
    virtual ~CwclGattClient();

    /// <summary> Connects to a remote Bluetooth LE device. </summary>
    /// <param name="Radio"> The <see cref="CwclBluetoothRadio" /> object used
    ///   to communicate with a remote Bluetooth device. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> The method starts connection to a remote Bluetooth LE device.
    ///   When connection operation completed the <c>OnConnected</c> event will
    ///   fire. The operation result will be passed into the <c>OnConnected</c>
    ///   event. </remarks>
    int Connect(CwclBluetoothRadio* const Radio);
    /// <summary> Disconnects from a remote device. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    int Disconnect();

	/// <summary> The method searches the characteristic in given service with
	///   the specified UUID. </summary>
	/// <param name="Service"> The GATT services. </param>
	/// <param name="Uuid"> The required characteristic's UUID. </param>
	/// <param name="Characteristic"> If the method completed with success on
	///   output contains the required characteristic. If the method failed the
	///   value is undefined. </param>
	/// <param name="Flag"> Operation behavior flag. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclGattService" />
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="wclGattCharacteristic" />
	/// <seealso cref="wclGattOperationFlag" />
    int FindCharacteristic(const wclGattService& Service, const wclGattUuid& Uuid,
		wclGattCharacteristic& Characteristic, const wclGattOperationFlag Flag = goNone);
	/// <summary> The method searches the service with specified UUID. </summary>
	/// <param name="Uuid"> The required service's UUID. </param>
	/// <param name="Service"> If the method completed with success on output
	///   contains the required service. If the method failed the value is
	///   undefined. </param>
	/// <param name="Flag"> Operation behavior flag. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="wclGattService" />
	/// <seealso cref="wclGattOperationFlag" />
    int FindService(const wclGattUuid& Uuid, wclGattService& Service,
		const wclGattOperationFlag Flag = goNone);

    /// <summary> The method reads all the characteristics available for the
    ///   specified service. </summary>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Characteristics"> On output a list of the service's
    ///   characteristics. An application is responsible to clean up a memory
    ///   allocated for the dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattCharacteristics" />
    int ReadCharacteristics(const wclGattService& Service, const wclGattOperationFlag Flag,
		wclGattCharacteristics& Characteristics);
    /// <summary> The method reads the value of the specified
    ///   characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Value"> On output contains a pointer to the characteristic's value.
	///   An application is responsible to clean up a memory allocated for the value. </param>
	/// <param name="Length"> On output contains a characteristic value length in
	///   bytes. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattProtectionLevel" />
    int ReadCharacteristicValue(const wclGattCharacteristic& Characteristic,
		const wclGattOperationFlag Flag, unsigned char*& Value, unsigned long& Length,
		const wclGattProtectionLevel Protection = plNone);
    /// <summary> The method reads all the descriptors available for the
    ///   specified characteristic. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Descriptors"> On output contains the list of the
    ///   characteristic's descriptors. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattDescriptors" />
    int ReadDescriptors(const wclGattCharacteristic& Characteristic, const wclGattOperationFlag Flag,
		wclGattDescriptors& Descriptors);
    /// <summary> The method reads the value of the specified
    ///   descriptor. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Value"> A descriptor's value. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattDescriptor" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattDescriptorValue" />
	/// <seealso cref="wclGattProtectionLevel" />
    int ReadDescriptorValue(const wclGattDescriptor& Descriptor, const wclGattOperationFlag Flag,
		wclGattDescriptorValue& Value, const wclGattProtectionLevel Protection = plNone);
    /// <summary> The method reads all the included services available for a
    ///   given service. </summary>
    /// <param name="Service"> Parent service returned by the call to
    ///   the <c>ReadServices</c> method. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattService" />
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    int ReadIncludedServices(const wclGattService& Service, const wclGattOperationFlag Flag,
		wclGattServices& Services);
    /// <summary> Reads available services from a remote Bluetooth LE
    ///   device. </summary>
    /// <param name="Flag"> Operation behavior flag. </param>
    /// <param name="Services"> On output a list of available GATT services.
    ///   An application is responsible to clean up a memory allocated for the
    ///   dynamic array. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattOperationFlag" />
    /// <seealso cref="wclGattServices" />
    int ReadServices(const wclGattOperationFlag Flag, wclGattServices& Services);

	/// <summary> The method writes the specified characteristic value to the
    ///   Bluetooth device. </summary>
    /// <param name="Characteristic"> A <see cref="wclGattCharacteristic" />
    ///   structure obtained by previous call to the <c>ReadCaracteristics</c>
    ///   method. </param>
    /// <param name="Value"> A pointer to the characteristic's value. </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
	/// <param name="WriteKind"> The write operation mode. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattProtectionLevel" />
	/// <seealso cref="wclGattWriteKind" />
    int WriteCharacteristicValue(const wclGattCharacteristic& Characteristic,
		const unsigned char* const Value, const unsigned long Length,
		const wclGattProtectionLevel Protection = plNone,
		const wclGattWriteKind WriteKind = wkAuto);
    /// <summary> The method writes the specified descriptor value to the
    ///   Bluetooth device. </summary>
    /// <param name="Descriptor"> A <see cref="wclGattDescriptor" /> obtained
    ///   by previous call to the <c>ReadDescriptors</c> method. </param>
    /// <param name="Value"> A descriptor's value. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattDescriptor" />
    /// <seealso cref="wclGattDescriptorValue" />
	/// <seealso cref="wclGattProtectionLevel" />
    int WriteDescriptorValue(const wclGattDescriptor& Descriptor,
		const wclGattDescriptorValue& Value,
		const wclGattProtectionLevel Protection = plNone);
	
	/// <summary> Writes the client configuration descriptor to the
    ///   device. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is interested. </param>
    /// <param name="Subscribe"> The value indicates should we subscribe
    ///   or unsubscribe from the characteristic value changes. </param>
    /// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
    ///   level. </param>
	/// <param name="SubscribeKind"> Indicates a characteristic value change
	///   notification method that should be used. If a characteristic has both
	///   <c>IsIndicatable</c> and <c>IsNotifiable</c> properties set then this
	///   parameter allows to control which notification method should be
	///   used. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> In order to receive notifications about characteristic
    ///   value changes the client must set the Client Configuration Descriptor.
    ///   An application can use this method to do it in easy way. </remarks>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
	/// <seealso cref="wclGattSubscribeKind" />
    int WriteClientConfiguration(const wclGattCharacteristic& Characteristic,
		const bool Subscribe, const wclGattOperationFlag Flag,
		const wclGattProtectionLevel Protection = plNone,
		const wclGattSubscribeKind SubscribeKind = skManual);

    /// <summary> Subscribes for the characteristic changes
    ///   notifications. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is interested. </param>
	/// <param name="SubscribeKind"> Indicates a characteristic value change
	///   notification method that should be used. If a characteristic has both
	///   <c>IsIndicatable</c> and <c>IsNotifiable</c> properties set then this
	///   parameter allows to control which notification method should be
	///   used. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattSubscribeKind" />
    int Subscribe(const wclGattCharacteristic& Characteristic,
		wclGattSubscribeKind SubscribeKind = skManual);
    /// <summary> Unsubscribes from the characteristic changes
    ///   notifications. </summary>
    /// <param name="Characteristic"> A characteristic object in that changes
    ///   an application is not interested any more. </param>
	/// <param name="SubscribeKind"> Indicates a characteristic value change
	///   notification method that should be used. If a characteristic has both
	///   <c>IsIndicatable</c> and <c>IsNotifiable</c> properties set then this
	///   parameter allows to control which notification method should be
	///   used. </param>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <seealso cref="wclGattCharacteristic" />
    /// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattSubscribeKind" />
    int Unsubscribe(const wclGattCharacteristic& Characteristic,
		const wclGattSubscribeKind SubscribeKind = skManual);
	
	/// <summary> Subscribes for the characteristic changes
	///   notifications and writes the client configuration descriptor to the
	///   device. </summary>
	/// <param name="Characteristic"> A characteristic object in that changes
	///   an application is interested. </param>
	/// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
	///   level. </param>
	/// <param name="SubscribeKind"> Indicates a characteristic value change
	///   notification method that should be used. If a characteristic has both
	///   <c>IsIndicatable</c> and <c>IsNotifiable</c> properties set then this
	///   parameter allows to control which notification method should be
	///   used. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> You can use this method to replace calls to the
	///   <c>Subscribe</c> and to the <c>WriteClientConfiguration</c>
	///   methods. </remarks>
	/// <seealso cref="wclGattCharacteristic" />
	/// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
	/// <seealso cref="wclGattSubscribeKind" />
	int SubscribeForNotifications(const wclGattCharacteristic& Characteristic,
		const wclGattOperationFlag Flag = goNone,
		const wclGattProtectionLevel Protection = plNone,
		const wclGattSubscribeKind SubscribeKind = skManual);
	/// <summary> Unsubscribes from the characteristic changes
	///   notifications and writes the client configuration descriptor to the
	///   device. </summary>
	/// <param name="Characteristic"> A characteristic object in that changes
	///   an application is interested. </param>
	/// <param name="Flag"> Operation behavior flag. </param>
	/// <param name="Protection"> Describes the required protection
	///   level. </param>
	/// <param name="SubscribeKind"> Indicates a characteristic value change
	///   notification method that should be used. If a characteristic has both
	///   <c>IsIndicatable</c> and <c>IsNotifiable</c> properties set then this
	///   parameter allows to control which notification method should be
	///   used. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> You can use this method to replace calls to the
	///   <c>Unsubscribe</c> and to the <c>WriteClientConfiguration</c>
	///   methods. </remarks>
	/// <seealso cref="wclGattCharacteristic" />
	/// <seealso cref="wclGattOperationFlag" />
	/// <seealso cref="wclGattProtectionLevel" />
	/// <seealso cref="wclGattSubscribeKind" />
	int UnsubscribeFromNotifications(const wclGattCharacteristic& Characteristic,
		const wclGattOperationFlag Flag = goNone,
		const wclGattProtectionLevel Protection = plNone,
		const wclGattSubscribeKind SubscribeKind = skManual);

	/// <summary> Gets the current connection parameters. </summary>
	/// <param name="Params"> If the function completed with success on output
	///   contains the current connection parameters. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParameters" />
	int GetConnectionParams(wclBluetoothLeConnectionParameters& Params);
	/// <summary> Request the connection parameters change to the specified
	///   preferred connection parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   type. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> When performing firmware updates, higher throughput is
	///   necessary to complete the operation swiftly for the user. In those
	///   scenarios, you should request <c>ppThroughputOptimized</c> connection
	///   parameters for the duration of the firmware update. That will reduce
	///   the number of concurrent connections to other Bluetooth peripherals,
	///   and should be used sparingly. </para>
	///   <para> Conversely, when connecting to multiple LE devices
	///   concurrently, you should use <c>ppPowerOptimized</c>. That will
	///   increase the acceptable peripheral latency for the connection,
	///   reducing the interval at which the LE device must respond to the
	///   host OS. That allows the local Bluetooth radio to schedule more
	///   connections concurrently, and reduces power usage on both the host OS
	///   and on the peripheral device. </para>
	///   <para> If the connection parameters were changed successfully the
	///   <c>OnConnectionParamsChanged</c> even fires. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersType" />
	int SetConnectionParams(const wclBluetoothLeConnectionParametersType Params);
	/// <summary> Request the connection parameters change to the specified
	///   preferred connection parameters. </summary>
	/// <param name="Params"> The preferred Bluetooth LE connection parameters
	///   value. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks><para> If the connection parameters were changed successfully
	///   the <c>OnConnectionParamsChanged</c> even fires. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	/// <seealso cref="wclBluetoothLeConnectionParametersValue" />
	int SetConnectionParams(const wclBluetoothLeConnectionParametersValue& Params);

	/// <summary> Reads the maximum PDU size for the current connection. </summary>
	/// <param name="Size"> If the method completed with success on output
	///   contains the maximum PDU size. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> The PDU size includes header and payload. For example if
	///   PDU size is 23 bytes the allowed payload is 20 bytes. </remarks>
	int GetMaxPduSize(unsigned short& Size);

	/// <summary> Reads the Bluetooth LE physical layer (PHY)
	///   information. </summary>
	/// <param name="Info"> If the method completed with success on output
	///   contains the connection PHY information. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclBluetoothLeConnectionPhy" />
	int GetConnectionPhyInfo(wclBluetoothLeConnectionPhy& Info);

    /// <summary> Gets the Radio used for connection. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object that used for
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the Radio used for connection. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object that used for
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the client state. </summary>
    /// <returns> The client state. </returns>
    /// <seealso cref="wclClientState" />
    wclClientState GetState() const;
	/// <summary> Gets the client state. </summary>
    /// <value> The client state. </value>
    /// <seealso cref="wclClientState" />
	__declspec(property(get = GetState)) wclClientState State;

    /// <summary> Gets a target Bluetooth device's MAC
    ///   address. </summary>
    /// <returns> The Bluetooth MAC address. </returns>
    __int64 GetAddress() const;
	/// <summary> Sets a target Bluetooth device's MAC
    ///   address. </summary>
    /// <param name="Value"> The Bluetooth MAC address. </param>
    /// <remarks> If an application changes the property when connection is
    ///   active the <see cref="wclEGattClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEGattClient"></exception>
    void SetAddress(const __int64 Value);
	/// <summary> Gets and sets a target Bluetooth device's MAC
    ///   address. </summary>
    /// <value> The Bluetooth MAC address. </value>
    /// <remarks> If an application changes the property when connection is
    ///   active the <see cref="wclEGattClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEGattClient"></exception>
	__declspec(property(get = GetAddress, put = SetAddress)) __int64 Address;

	/// <summary> Gets connection mode. </summary>
    /// <returns> The Boolean indicates the connection mode. </returns>
	/// <remarks> If this property set to <c>True</c> the connection to a target
	///   device will be executed on first services read or when the OS decided
	///   to do that. If the property is <c>False</c> the connection will be
	///   executed (if possible) on <c>Connect</c> call. </remarks>
	bool GetConnectOnRead() const;
	/// <summary> Sets connection mode. </summary>
	/// <param name="Value"> The Boolean indicates the connection mode. </param>
	/// <remarks> If this property set to <c>True</c> the connection to a target
	///   device will be executed on first services read or when the OS decided
	///   to do that. If the property is <c>False</c> the connection will be
	///   executed (if possible) on <c>Connect</c> call. </remarks>
	/// <exception cref="wclEGattClient"></exception>
	void SetConnectOnRead(const bool Value);
	/// <summary> Gets and sets connection mode. </summary>
    /// <value> The Boolean indicates the connection mode. </value>
    /// <remarks> If this property set to <c>True</c> the connection to a target
    ///   device will be executed on first services read or when the OS decided
    ///   to do that. If the property is <c>False</c> the connection will be
    ///   executed (if possible) on <c>Connect</c> call. </remarks>
    /// <exception cref="wclEGattClient"></exception>
	__declspec(property(get = GetConnectOnRead, put = SetConnectOnRead))
		bool ConnectOnRead;

	/// <summary> Gets the notifications mode. </summary>
	/// <returns> The Boolean indicates the notifications mode. </returns>
	/// <remarks> If this property set to <c>True</c> the characteristic value
	///   changes notification (and/or indication) will work correctly with
	///   some boards (such as <c>Bluno</c>, <c>Bluno Meag</c> and some others)
	///   that do not have <c>Characteristic Client Configucation
	///   Descriptor</c>. </remarks>
	bool GetForceNotifications() const;
	/// <summary> Sets the notifications mode. </summary>
	/// <param name="Value"> The Boolean indicates the notifications mode. </param>
	/// <remarks> If this property set to <c>True</c> the characteristic value
	///   changes notification (and/or indication) will work correctly with
	///   some boards (such as <c>Bluno</c>, <c>Bluno Meag</c> and some others)
	///   that do not have <c>Characteristic Client Configucation
	///   Descriptor</c>. </remarks>
	void SetForceNotifications(const bool Value);
	/// <summary> Gets and sets the notifications mode. </summary>
    /// <value> The Boolean indicates the notifications mode. </value>
    /// <remarks> If this property set to <c>True</c> the characteristic value
    ///   changes notification (and/or indication) will work correctly with
    ///   some boards (such as <c>Bluno</c>, <c>Bluno Meag</c> and some others)
    ///   that do not have <c>Characteristic Client Configucation
    ///   Descriptor</c>. </remarks>
    /// <exception cref="wclEGattClient"></exception>
	__declspec(property(get = GetForceNotifications, put = SetForceNotifications))
		bool ForceNotifications;

    /// <summary> The event fires when a subscribed characteristic value has
    ///   been changed. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Handle"> A changed characteristic handle. </param>
	/// <param name="Value"> A pointer to the characteristic value. </param>
	/// <param name="Length"> A characteristic value length in bytes. </param>
	/// <remarks> <para> The <c>Value</c> parameter is valid only inside the event
	///   handler. If an application needs to use it outside the event handler
	///   it must be copied. </para>
	///   <para> To receive characteristic value change events an application
    ///   must first subscribe for characteristic changes notification
	///   by calling <c>Subscribe</c> method. </para> </remarks>
	wclGattCharacteristicChangedEvent(OnCharacteristicChanged);
    /// <summary> The event fires when a connection to a remote device has been
    ///   established. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
    /// <remarks> If the <c>Error</c> parameter of the event is not
    ///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
    ///   method again from inside the event handler. </remarks>
    wclClientConnectionConnectEvent(OnConnect);
	/// <summary> The event fires when the connection parameters
	///   changed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <remarks> <para> Once this event received an application can use the
	///   <c>GetConnectionParams</c> method to retrieve the current connection
	///   parameters. </para>
	///   <para> This feature is supported with <c>BLED112</c> dongle and with
	///   <c>Microsoft</c> Bluetooth drivers on <c>Windows 11</c> and
	///   above. </para> </remarks>
	wclNotifyEvent(OnConnectionParamsChanged);
	/// <summary> The event fires when the connection PHY changed. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    /// <remarks> <para> Once this event received an application can use the
    ///   <c>GetConnectionParams</c> method to get the current connection
    ///   parameters. </para>
    ///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </para> </remarks>
    wclNotifyEvent(OnConnectionPhyChanged);
    /// <summary> The even fires when a connection to a remote device has been
    ///   closed. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
    wclClientConnectionDisconnectEvent(OnDisconnect);
	/// <summary> The event fires when the maximum PDU size changed. </summary>
	/// <remarks> Once the event fires an application can use the
	///   <c>GetMaxPduSize</c> method to read the current maximum PDU
	///   size. </remarks>
	wclNotifyEvent(OnMaxPduSizeChanged);
};

/// <summary> Bluetooth Low Energy GATT server. </summary>
/// <remarks> The <c>TwclGattServer</c> component enables an
///   application to act as GATT peripheral device. </remarks>
/// <seealso cref="CwclBluetoothComponent" />
class CwclGattServer : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclGattServer);
	
private:
	CwclGattServerConnection* FServer;
	
	void CharacteristicRead(void* Sender, CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicReadRequest* const Request);
	void CharacteristicWrite(void* Sender, CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicWriteRequest* const Request);
	void ClientConnected(void* Sender, CwclGattServerClient* const Client);
	void ClientDisconnected(void* Sender, CwclGattServerClient* const Client);
	void ClientSubscribed(void* Sender, CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	void ClientUnsubscribed(void* Sender, CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	void ConnectionParamsChanged(void* Sender, CwclGattServerClient* const Client);
	void ConnectionPhyChanged(void* Sender, CwclGattServerClient* const Client);
	void MaxPduSizeChanged(void* Sender, CwclGattServerClient* const Client);
	void NotificationSizeChanged(void* Sender, CwclGattServerClient* const Client);
	void ServerStarted(void* Sender);
	void ServerStopped(void* Sender);
	
protected:
	/// <summary> Fires the <c>OnClientConnected</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a connected client. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoClientConnected(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnClientDisconnected</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a disconnected client. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoClientDisconnected(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnConnectionParamsChanged</c> event. </summary>
    /// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that represents a disconnected client. </param>
    /// <seealso cref="CwclGattServerClient" />
	virtual void DoConnectionParamsChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnConnectionPhyChanged</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that represents a disconnected client. </param>
    /// <seealso cref="CwclGattServerClient" />
    virtual void DoConnectionPhyChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnMaxPduSizeChanged</c> event. </summary>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoMaxPduSizeChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnNotificationSizeChanged</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
	///   that represents a client which changed the maximum notification
	///   size. </param>
	/// <seealso cref="CwclGattServerClient" />
	virtual void DoNotificationSizeChanged(CwclGattServerClient* const Client);
	/// <summary> Fires the <c>OnRead</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that requested read. </param>
	/// <param name="Characteristic"> The local GATT characteristic object
	///   that requested the write operation. </param>
	/// <param name="Request"> The GATT read request object. </param>
	/// <remarks> This method is called when a remote GATT client requests
	///   read from the characteristic. An application must call the
	///   <c>Respond</c> method to send a data back to the device. </remarks>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="CwclGattLocalCharacteristicReadRequest" />
	virtual void DoRead(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicReadRequest* const Request);
	/// <summary> Fires the <c>OnStarted</c> event. </summary>
	virtual void DoStarted();
	/// <summary> Fires the <c>OnStopped</c> event. </summary>
	virtual void DoStopped();
	/// <summary> Fires the <c>OnSubscribed</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that subscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void DoSubscribed(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	/// <summary> Fires the <c>OnUnsubscribed</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	virtual void DoUnsubscribed(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic);
	/// <summary> Fires the <c>OnWrite</c> event. </summary>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object
    ///   that requested write. </param>
	/// <param name="Characteristic"> The local GATT characteristic object
	///   that requested the write operation. </param>
	/// <param name="Request"> The GATT characteristic write request
    ///   object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="CwclGattLocalCharacteristicWriteRequest" />
	virtual void DoWrite(CwclGattServerClient* const Client,
		CwclGattLocalCharacteristic* const Characteristic,
		CwclGattLocalCharacteristicWriteRequest* const Request);
	
public:
	/// <summary> Creates new component. </summary>
	CwclGattServer();
	/// <summary> Frees the component. </summary>
	/// <remarks> The component must always be destroyed in the same thread it
	///   was created. </remarks>
	virtual ~CwclGattServer();
	
	/// <summary> Initializes Bluetooth LE GATT Server. </summary>
	/// <param name="Radio"> The <see cref="CwclBluetoothRadio" /> object used
	///   to communicate with a remote Bluetooth device. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> Before adding services and characteristics an
	///   application must initialize the server by calling this method. </para>
	///   <para> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers or on any other Windows platform with BlueSoleil
	///   Bluetooth drivers. </para> </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	int Initialize(CwclBluetoothRadio* const Radio);
	/// <summary> Uninitializes the Bluetooth LE GATT Server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> <para> An application must call this method after stopping the
	///   server to release all allocated resources. </para>
	///   <para> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers or on any other Windows platform with BlueSoleil
	///   Bluetooth drivers. </para> </remarks>
	int Uninitialize();
	
	/// <summary> Starts the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Start();
	/// <summary> Stops the GATT server. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Stop();
	
	/// <summary> Creates new local GATT service and adds it to the services
	///   list. </summary>
	/// <param name="Uuid"> The service's UUID. </param>
	/// <param name="Service"> If the function completed with success this
	///   parameter receives a just created GATT local service object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclGattUuid" />
	/// <seealso cref="CwclGattLocalService" />
	int AddService(const wclGattUuid& Uuid, CwclGattLocalService*& Service);
	/// <summary> Clears the local services list. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int ClearServices();
	/// <summary> Deletes the service with given index. </summary>
	/// <param name="Index"> The service's index. The parameter must be in range
	///   between 0 and ServicesCount - 1. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int DeleteService(const size_t Index);
	
	/// <summary> Gets the server's state. </summary>
	/// <returns> <c>True</c> if the server is running. </returns>
	bool GetInitialized() const;
	/// <summary> Gets the server's state. </summary>
	/// <value> <c>True</c> if the server is running. </value>
	__declspec(property(get = GetInitialized)) bool Initialized;

	/// <summary> Gets the server's owner. </summary>
	/// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the server's owner. </summary>
	/// <value> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </value>
	/// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the server running status. </summary>
	/// <returns> <c>True</c> if the server is advertising. </returns>
	bool GetStarted() const;
	/// <summary> Gets the server running status. </summary>
	/// <value> <c>True</c> if the server is advertising. </value>
	__declspec(property(get = GetStarted)) bool Started;
	
	/// <summary> Gets the local GATT service by its index. </summary>
	/// <param name="Index"> The service's index. The parameter must be in range
	///   between 0 and ServicesCount - 1. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <returns> The local GATT service object. </returns>
	/// <seealso cref="CwclGattLocalService" />
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEGattServer"></exception>
	CwclGattLocalService* GetServices(const size_t Index) const;
	/// <summary> Gets the local GATT service by its index. </summary>
	/// <value> The local GATT service object. </value>
	/// <seealso cref="CwclGattLocalService" />
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEGattServer"></exception>
	__declspec(property(get = GetServices)) CwclGattLocalService* Services[];

	/// <summary> Gets the services count. </summary>
	/// <returns> The services count. </returns>
	size_t GetServicesCount() const;
	/// <summary> Gets the services count. </summary>
	/// <value> The services count. </value>
	__declspec(property(get = GetServicesCount)) size_t ServicesCount;

	/// <summary> Gets the GATT server client by its index. </summary>
	/// <param name="Index"> The client's index. The parameter must be in range
	///   between 0 and ClientsCount - 1. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <returns> The GATT server client object. </returns>
	/// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclGattServerClient* GetClients(const size_t Index) const;
	/// <summary> Gets the GATT server client by its index. </summary>
	/// <value> The GATT server client object. </value>
	/// <seealso cref="CwclGattServerClient" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetClients)) CwclGattServerClient* Clients[];

	/// <summary> Gets the clients count. </summary>
	/// <returns> The clients count. </returns>
	size_t GetClientsCount() const;
	/// <summary> Gets the clients count. </summary>
	/// <value> The clients count. </value>
	__declspec(property(get = GetClientsCount)) size_t ClientsCount;

	/// <summary> The event fires when a client connected to the
	///   server. </summary>
	/// <summary> The GATT server client event handlers prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnClientConnected);
    /// <summary> The event fires when a client disconnected from
	///   the server. </summary>
	/// <summary> The GATT server client event handlers prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnClientDisconnected);
	/// <summary> The event fires when the connection parameters
    ///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
    /// <remarks> <para> Once this event received an application can use the
    ///   <c>GetConnectionParams</c> method to get the current connection
    ///   parameters. </para>
    ///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
    ///   drivers on <c>Windows 11</c> and above. </para> </remarks>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnConnectionParamsChanged);
	/// <summary> The event fires when the connection PHY changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <remarks> <para> Once this event received an application can use the
	///   <c>GetConnectionPhyInfo</c> method to get the current connection
	///   parameters. </para>
	///   <para> This feature is supported with <c>Microsoft</c> Bluetooth
	///   drivers on <c>Windows 11</c> and above. </para> </remarks>
	/// <seealso cref="CwclGattServerClient" />
	wclGattServerClientEvent(OnConnectionPhyChanged);
	/// <summary> The event fires when maximum PDU size changed for the
    ///   connected client. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnMaxPduSizeChanged);
	/// <summary> The event fires when a maximum notification size of a
    ///   subscribed client has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   represents a GATT server client. </param>
	/// <seealso cref="CwclGattServerClient" />
    wclGattServerClientEvent(OnNotificationSizeChanged);
	/// <summary> The event fires when a remote GATT client requests
	///   characteristic's data read. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   requested read. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <param name="Request"> The GATT read request object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="TwclGattLocalCharacteristicReadRequest" />
	wclGattLocalCharacteristicReadEvent(OnRead);
	/// <summary> The event fires when the Bluetooth LE GATT Server has been
	///   successfully started. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStarted);
	/// <summary> The event fires when the Bluetooth LE GATT Server has been
	///   stopped. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStopped);
	/// <summary> The event fires when a remote GATT client subscribes to the
    ///   characteristic changes notifications or indications. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   subscribed or unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	wclGattLocalCharacteristicSubscribedClientsChangedEvent(OnSubscribed);
    /// <summary> The event fires when a remote GATT client unsubscribes from
    ///   the characteristic changes notifications or indications. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   subscribed or unsubscribed. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	wclGattLocalCharacteristicSubscribedClientsChangedEvent(OnUnsubscribed);
	/// <summary> The event fires when a remote device writes data to the
	///   characteristic. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Client"> The <see cref="CwclGattServerClient" /> object that
	///   requested write. </param>
	/// <param name="Characteristic"> The characteristic object for which writes
	///   is executing. </param>
	/// <param name="Request"> The GATT characteristic write request object. </param>
	/// <seealso cref="CwclGattServerClient" />
	/// <seealso cref="CwclGattLocalCharacteristic" />
	/// <seealso cref="TwclGattLocalCharacteristicWriteRequest" />
	wclGattLocalCharacteristicWriteEvent(OnWrite);
};

/// <summary> The Bluetooth LE Beacon watcher. </summary>
/// <remarks> The component allows to monitor Bluetooth LE Beacon advertisement
///   packets. </remarks>
/// <seealso cref="CwclBluetoothComponent" />
class CwclBluetoothLeBeaconWatcher : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclBluetoothLeBeaconWatcher);

private:
	bool									FActive;
	CwclBluetoothLeBeaconWatcherConnection*	FWatcher;
	
	void WatcherAdvertisementAppearanceFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Appearance);
	void WatcherAdvertisementFrameInformation(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const tstring& Name,
		const wclBluetoothLeAdvertisementType PacketType,
		const wclBluetoothLeAdvertisementFlags& Flags);
	void WatcherAdvertisementExtFrameInformation(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const wclBluetoothAddressType AddressType,
		const char TxPower, const wclBluetoothLeExtendedFrameFlags& Flags);
	void WatcherAdvertisementRawFrame(void* Sender, const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned char DataType,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherAdvertisementReceived(void* Sender, const __int64 Address, const __int64 Timestamp,
		const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherAdvertisementService16DataFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherAdvertisementService32DataFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherAdvertisementService128DataFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherAdvertisementServiceSol16Frame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid);
	void WatcherAdvertisementServiceSol32Frame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid);
	void WatcherAdvertisementServiceSol128Frame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const GUID& Uuid);
	void WatcherAdvertisementTxPowerLevelFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const char TxPower);
	void WatcherAdvertisementUuidFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const GUID& Uuid);
	void WatcherAltBeaconFrame(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);
	void WatcherEddystoneTlmFrame(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);
	void WatcherEddystoneUidFrame(void* Sender, const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherEddystoneUrlFrame(void* Sender, const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const tstring& Url);
	void WatcherManufacturerRawFrame(void* Sender, const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short CompanyId,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	void WatcherProximityBeaconFrame(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 wclBluetoothLeAdvertisementFrameRawData& Data);
	
	void WatcherStarted(void* Sender);
	void WatcherStopped(void* Sender);

protected:
	/// <summary> Fires the <c>OnAdvertisementAppearanceFrame</c>
	///   event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Appearance"> The Bluetooth LE device appearance
	///   value. </param>
    virtual void DoAdvertisementAppearanceFrame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Appearance);
	/// <summary> Fires the <c>OnAdvertisementFrameInformation</c>
	///   event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Name"> The Bluetooth LE advertiser's name. </param>
	/// <param name="PacketType"> The Bluetooth LE advertisement data packet
	///   type. </param>
	/// <param name="Flags"> The Bluetooth LE advertisement packet payload
	///   flags. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementType" />
    /// <seealso cref="wclBluetoothLeAdvertisementFlags" />
	virtual void DoAdvertisementFrameInformation(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const tstring& Name,
		const wclBluetoothLeAdvertisementType PacketType,
		const wclBluetoothLeAdvertisementFlags& Flags);
	/// <summary> Fires the <c>OnAdvertisementExtFrameInformation</c>
	///   event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AddressType"> The Bluetooth LE address type. </param>
	/// <param name="TxPower"> The received transmit power of the
	///   advertisement. Ranges from -127 dBm to 20 dBm. -128 indicates
	///   "no value". </param>
	/// <param name="Flags"> The Bluetooth LE advertisement extended frame
	///   flags. </param>
	/// <seealso cref="wclBluetoothAddressType" />
	/// <seealso cref="wclBluetoothLeExtendedFrameFlags" />
	virtual void DoAdvertisementExtFrameInformation(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const wclBluetoothAddressType AddressType,
		const char TxPower, const wclBluetoothLeExtendedFrameFlags& Flags);
    /// <summary> Fires the <c>OnAdvertisementRawFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="DataType"> The frame's data type. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>NULL</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementRawFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned char DataType,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnAdvertisementReceived</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>nil</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementReceived(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService16DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService16DataFrame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService32DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService32DataFrame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnService128DataFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAdvertisementService128DataFrame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
	/// <summary> Fires the <c>OnServiceSol16Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol16Frame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid);
	/// <summary> Fires the <c>OnServiceSol32Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol32Frame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid);
	/// <summary> Fires the <c>OnServiceSol128Frame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bit service UUID. </param>
	virtual void DoAdvertisementServiceSol128Frame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const GUID& Uuid);
	/// <summary> Fires the <c>OnAdvertisementTxPowerLevelFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxPower"> The TX power level in range from -127 to 128
	///   dBm. </param>
	virtual void DoAdvertisementTxPowerLevelFrame(const __int64 Address,
		const __int64 Timestamp, const char Rssi, const char TxPower);
	/// <summary> Fires the <c>OnAdvertisementUuidFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The advertised UUID value. </param>
	virtual void DoAdvertisementUuidFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const GUID& Uuid);
	/// <summary> Fires the <c>OnAltBeaconFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Reserved"> A 1-byte value from 0x00 to 0xFF. Interpretation
	///   of this value is to be defined by the manufacturer and is to be
	///   evaluated based on the CompanyId value. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoAltBeaconFrame(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);
    /// <summary> Fires the <c>OnEddystoneTlmFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AdvCnt"> The running count of advertisement frames of all
	///   types emitted by the beacon since power-up or reboot, useful for
	///   monitoring performance metrics that scale per broadcast frame.
	///   If this value is reset (e.g. on reboot), the current time field is
	///   also reset. </param>
	/// <param name="Batt"> The current battery charge in millivolts, expressed
	///   as 1 mV per bit. If not supported (for example in a USB-powered
	///   beacon) the value should be zeroed. </param>
	/// <param name="SecCnt"> The 0.1 second resolution counter that represents
	///   time since beacon power-up or reboot. If this value is reset (e.g. on
	///   a reboot), the AdvCnt count field is also reset. </param>
	/// <param name="Temp"> The beacon temperature in degrees Celsius sensed by
	///   the beacon. If not supported the value is -128 °C. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoEddystoneTlmFrame(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);
    /// <summary> Fires the <c>OnEddystoneUidFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
    ///   -100 dBm and +20 dBm at 1 dBm resolution measured at 0 meter
    ///   distance. </param>
    /// <param name="Uuid"> The Eddystone ID: 10 bytes - Namespace ID and 6
    ///   bytes - Instance ID. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    virtual void DoEddystoneUidFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const GUID& Uuid,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
    /// <summary> Fires the <c>OnEddystoneUrlFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
    ///   -100 dBm and +20 dBm at 1 dBm resolution measured at 0 meter
    ///   distance. </param>
    /// <param name="Url"> The Eddystone URL. </param>
    virtual void DoEddystoneUrlFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const char TxRssi, const tstring& Url);
    /// <summary> Fires the <c>OnManufacturerRawFrame</c> event. </summary>
    /// <param name="Address"> The Bluetooth LE advertiser's MAC
    ///   address. </param>
    /// <param name="Timestamp"> The frame's timestamp in Universal Time
    ///   format. </param>
    /// <param name="Rssi"> The measured RSSI value in dBm at range between -100
    ///   dBm and +20 dBm at 1 dBm resolution. </param>
    /// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
    ///   Bluetooth SIG Assigned Numbers. </param>
    /// <param name="Data"> The frame raw data. The value can be <c>NULL</c> if
    ///   there is no any data available in the frame. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    virtual void DoManufacturerRawFrame(const __int64 Address, const __int64 Timestamp,
		const char Rssi, const unsigned short CompanyId,
		const wclBluetoothLeAdvertisementFrameRawData& Data);
    /// <summary> Fires the <c>OnProximityBeaconFrame</c> event. </summary>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC
	///   address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between
	///   -100 dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Data"> The additional frame data. </param>
    /// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	virtual void DoProximityBeaconFrame(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 wclBluetoothLeAdvertisementFrameRawData& Data);
	
    /// <summary> Fires the <c>OnStarted</c> event. </summary>
    virtual void DoStarted();
    /// <summary> Fires the <c>OnStopped</c> event. </summary>
    virtual void DoStopped();

public:
    /// <summary> Creates new component. </summary>
    CwclBluetoothLeBeaconWatcher();
    /// <summary> Frees the component. </summary>
    /// <remarks> The component must always be destroyed in the same thread it
    ///   was created. </remarks>
    virtual ~CwclBluetoothLeBeaconWatcher();
	
	/// <summary> Starts monitoring for Bluetooth LE Beacons. </summary>
    /// <param name="Radio"> The <see cref="CwclBluetoothRadio" /> object used
    ///   to communicate with a remote Bluetooth device. </param>
	/// <param name="ScanningMode"> Specifies the Bluetooth LE scanning
	///   mode. </param>
	/// <param name="ScanInterval"> Specifies the Bluetooth LE scan in 0.625 ms
    ///   units. The value must be in range between
    ///   <see cref="WCL_BLE_MIN_SCAN_INTERVAL" /> and
    ///   <see cref="WCL_BLE_MAX_SCAN_INTERVAL" />. The default value is
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" />. </param>
	/// <param name="ScanWindow"> Specifies the Bluetooth LE scan window in
    ///   0.625 ms units. The value must be in range between
    ///   <see cref="WCL_BLE_MIN_SCAN_WINDOW" /> and
    ///   <see cref="WCL_BLE_MAX_SCAN_WINDOW" />. The default value is
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" />. The scan window must be
    ///   less or equal to <c>ScanInterval</c>. </param>
	/// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers only. If the method returns error try to call this
	///   method with default scan parameters. </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="wclBluetoothLeScanningMode" />
	/// <seealso cref="WCL_BLE_MIN_SCAN_WINDOW" />
    /// <seealso cref="WCL_BLE_MAX_SCAN_WINDOW" />
    /// <seealso cref="WCL_BLE_DEFAULT_SCAN_WINDOW" />
	int Start(CwclBluetoothRadio* const Radio,
		const wclBluetoothLeScanningMode ScanningMode = smActive,
		const unsigned short ScanInterval = WCL_BLE_DEFAULT_SCAN_INTERVAL,
		const unsigned short ScanWindow = WCL_BLE_DEFAULT_SCAN_WINDOW);
    /// <summary> Stops monitoring for Bluetooth LE Beacons. </summary>
    /// <returns> If the function succeed the return value is
    ///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
    ///   the WCL error codes. </returns>
    /// <remarks> This feature is supported on Windows 10 with the Microsoft
    ///   Bluetooth drivers only. </remarks>
    int Stop();

    /// <summary> Gets Beacon Monitoring state. </summary>
    /// <returns> <c>True</c> if the Beacon monitoring is running. </returns>
    bool GetMonitoring() const;
	/// <summary> Gets Beacon Monitoring state. </summary>
    /// <value> <c>True</c> if the Beacon monitoring is running. </value>
	__declspec(property(get = GetMonitoring)) bool Monitoring;

	/// <summary> Gets the watcher owner. </summary>
    /// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </returns>
    /// <seealso cref="CwclBluetoothRadio" />
    CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the watcher owner. </summary>
    /// <value> The <see cref="CwclBluetoothRadio" /> object owns the
    ///   connection. </value>
    /// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the current scan interval value. </summary>
	/// <returns> The current scan interval. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" /> </returns>
    unsigned short GetScanInterval() const;
	/// <summary> Gets the current scan interval value. </summary>
	/// <value> The current scan interval. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_INTERVAL" /> </value>
	__declspec(property(get = GetScanInterval)) unsigned short ScanInterval;

	/// <summary> Gets the current scanning mode. </summary>
	/// <returns> The Bluetooth LE scanning mode. </returns>
	/// <seealso cref="wclBluetoothLeScanningMode" />
	wclBluetoothLeScanningMode GetScanningMode() const;
	/// <summary> Gets the current scanning mode. </summary>
	/// <value> The Bluetooth LE scanning mode. </value>
	/// <seealso cref="wclBluetoothLeScanningMode" />
	__declspec(property(get = GetScanningMode)) wclBluetoothLeScanningMode ScanningMode;

	/// <summary> Gets the current scan window value. </summary>
    /// <returns> The current scan window. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" /> </returns>
    unsigned short GetScanWindow() const;
	/// <summary> Gets the current scan window value. </summary>
    /// <value> The current scan window. If the watcher is stopped the
    ///   returning value is always
    ///   <see cref="WCL_BLE_DEFAULT_SCAN_WINDOW" /> </value>
	__declspec(property(get = GetScanWindow)) unsigned short ScanWindow;

	/// <summary> The event fires when an appearance advertisement frame
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Appearance"> The Bluetooth LE device appearance
	///   value. </param>
    wclBluetoothLeAdvertisementAppearanceFrameEvent(OnAdvertisementAppearanceFrame);
	/// <summary> The event fires when new Bluetooth LE advertisement frame
    ///   has been received and provides the common basic information about
    ///   the frame. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Name"> The Bluetooth LE advertiser's name. </param>
	/// <param name="PacketType"> The Bluetooth LE advertisement data packet
	///   type. </param>
	/// <param name="Flags"> The Bluetooth LE advertisement packet payload
	///   flags. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementType" />
	/// <seealso cref="wclBluetoothLeAdvertisementFlags" />
    wclBluetoothLeAdvertisementFrameInformationEvent(OnAdvertisementFrameInformation);
	/// <summary> The event fires when new Bluetooth LE advertisement
	///   extended frame has been received and provides the common basic
	///   information about the frame. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AddressType"> The Bluetooth LE address type. </param>
	/// <param name="TxPower"> The received transmit power of the
	///   advertisement. Ranges from -127 dBm to 20 dBm. -128 indicates
	///   "no value". </param>
	/// <param name="Flags"> The Bluetooth LE advertisement extended frame
	///   flags. </param>
	/// <seealso cref="wclBluetoothAddressType" />
	/// <seealso cref="wclBluetoothLeExtendedFrameFlags" />
	wclBluetoothLeAdvertisementExtFrameInformationEvent(OnAdvertisementExtFrameInformation);
    /// <summary> The <c>OnAdvertisementRawFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="DataType"> The frame's data type. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>NULL</c>. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeAdvertisementRawFrameEvent(OnAdvertisementRawFrame);
	/// <summary> The event fires when any Bluetooth LE advertisement frame
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Data"> The frame's raw bytes data. If there is no data the
	///   value is <c>nil</c>. </param>
	/// <remarks> Unlike the <c>OnAdvertisementRawFrame</c> and the
	///   <c>OnManufacturerRawFrame</c> this even fires for any Bluetooth LE
	///   advertisement and contains unparsed raw frame data. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementReceivedEvent(OnAdvertisementReceived);
	/// <summary> The event fires when a Bluetooth LE 16 bit Service Data
    ///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bit service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementService16DataFrameEvent(OnAdvertisementService16DataFrame);
	/// <summary> The event fires when a Bluetooth LE 32 bit Service Data
	///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bits service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementService32DataFrameEvent(OnAdvertisementService32DataFrame);
	/// <summary> The event fires when a Bluetooth LE 128 bit Service Data
	///   advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bits service UUID. </param>
	/// <param name="Data"> The service data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeAdvertisementService128DataFrameEvent(OnAdvertisementService128DataFrame);
	/// <summary> The event fires when a Bluetooth LE 16 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 16 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol16FrameEvent(OnAdvertisementServiceSol16Frame);
	/// <summary> The event fires when a Bluetooth LE 32 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 32 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol32FrameEvent(OnAdvertisementServiceSol32Frame);
	/// <summary> The event fires when a Bluetooth LE 128 bit Service
	///   Solicitation advertisement frame received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The 128 bits service UUID. </param>
	wclBluetoothLeAdvertisementServiceSol128FrameEvent(OnAdvertisementServiceSol128Frame);
	/// <summary> The event fires when a TX power level advertisement frame
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxPower"> The TX power level in range from -127 to 128
	///   dBm. </param>
	wclBluetoothLeAdvertisementTxPowerLevelFrameEvent(OnAdvertisementTxPowerLevelFrame);
	/// <summary> The event fires when an UUID advertisement frame has been
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="Uuid"> The advertised UUID value. </param>
	wclBluetoothLeAdvertisementUuidFrameEvent(OnAdvertisementUuidFrame);
	/// <summary> The event fires when a Bluetooth LE Alt beacon
    ///   advertisement frame received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Reserved"> A 1-byte value from 0x00 to 0xFF. Interpretation
	///   of this value is to be defined by the manufacturer and is to be
	///   evaluated based on the CompanyId value. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeAltBeaconFrameEvent(OnAltBeaconFrame);
	/// <summary> The <c>OnEddystoneTlmFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="AdvCnt"> The running count of advertisement frames of all
	///   types emitted by the beacon since power-up or reboot, useful for
	///   monitoring performance metrics that scale per broadcast frame.
	///   If this value is reset (e.g. on reboot), the current time field is
	///   also reset. </param>
	/// <param name="Batt"> The current battery charge in millivolts, expressed as
	///   1 mV per bit. If not supported (for example in a USB-powered beacon) the
	///   value should be zeroed. </param>
	/// <param name="SecCnt"> The 0.1 second resolution counter that represents
	///   time since beacon power-up or reboot. If this value is reset (e.g. on
	///   a reboot), the AdvCnt count field is also reset. </param>
	/// <param name="Temp"> The beacon temperature in degrees Celsius sensed by
	///   the beacon. If not supported the value is -128 °C. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeEddystoneTlmFrameEvent(OnEddystoneTlmFrame);
	/// <summary> The <c>OnEddystoneUidFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
	///   distance. </param>
	/// <param name="Uuid"> The Eddystone ID: 10 bytes - Namespace ID and 6
	///   bytes - Instance ID. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeEddystoneUidFrameEvent(OnEddystoneUidFrame);
	/// <summary> The <c>OnEddystoneUrlFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 0 meter
	///   distance. </param>
	/// <param name="Url"> The Eddystone URL. </param>
    wclBluetoothLeEddystoneUrlFrameEvent(OnEddystoneUrlFrame);
	/// <summary> The <c>OnManufacturerRawFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Data"> The frame raw data. The value can be <c>NULL</c> if
	///   there is no any data available in the frame. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
    wclBluetoothLeManufacturerRawFrameEvent(OnManufacturerRawFrame);
	/// <summary> The <c>OnProximityBeaconFrame</c> event handler
	///   prototype. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Address"> The Bluetooth LE advertiser's MAC address. </param>
	/// <param name="Timestamp"> The frame's timestamp in Universal Time
	///   format. </param>
	/// <param name="Rssi"> The measured RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution. </param>
	/// <param name="CompanyId"> The beacon's manufacturer ID as defined in the
	///   Bluetooth SIG Assigned Numbers. </param>
	/// <param name="Major"> The beacon's Major value. </param>
	/// <param name="Minor"> The beacon's Minor value. </param>
	/// <param name="Uuid"> The beacon's UUID. </param>
	/// <param name="TxRssi"> The beacon's RSSI value in dBm at range between -100
	///   dBm and +20 dBm at 1 dBm resolution measured at 1 meter
	///   distance. </param>
	/// <param name="Data"> The additional frame data. </param>
	/// <seealso cref="wclBluetoothLeAdvertisementFrameRawData" />
	wclBluetoothLeProximityBeaconFrameEvent(OnProximityBeaconFrame);
	/// <summary> The event fires when the Bluetooth LE beacon monitoring
	///   started. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	wclNotifyEvent(OnStarted);
	/// <summary> The event fires when the Bluetooth LE beacon monitoring
	///   stopped. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	wclNotifyEvent(OnStopped);
};

/// <summary> The Bluetooth LE advertiser components. </summary>
/// <remarks> The feature is supported only on Windows 10 platform with
///   <c>Microsoft</c> Bluetooth drivers or on any Windows platform with
///   <c>BLED112</c> Bluetooth dongle. </remarks>
/// <seealso cref="CwclBluetoothComponent" />
class CwclBluetoothLeAdvertiser : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclBluetoothLeAdvertiser);

private:
	bool									FActive;
	WCL_BLE_ADV_LIST*						FAdvertisements;
	CwclBluetoothLeAdvertiserConnection*	FAdvertiser;
	
	/* Extended advertisement properties. */
	
	bool									FAnonymous;
	bool									FIncludeTxRssi;
	char									FPreferredTxRssi;
	bool									FUseExtendedAdvertisement;

	int CheckAdvertisement(const CwclBluetoothLeAdvertisement* const Advertisement) const;
	void DeleteAllAdvertisements();
	void DeleteAdvertisement(const size_t Index);

	/* Advertiser connection events. */

	void AdvertiserStarted(void* Sender);
	void AdvertiserStopped(void* Sender);
	
protected:
	/// <summary> Fires the <c>OnStarted</c> event. </summary>
	virtual void DoStarted();
	/// <summary> Fires the <c>OnStopped</c> event. </summary>
	virtual void DoStopped();
	
public:
	/// <summary> Creates new component. </summary>
	CwclBluetoothLeAdvertiser();
	/// <summary> Frees the component. </summary>
	/// <remarks> The component must always be destroyed in the same thread it
	///   was created. </remarks>
	virtual ~CwclBluetoothLeAdvertiser();

	/// <summary> Adds Bluetooth LE advertisement to the advertisements
	///   list. </summary>
	/// <param name="Advertisement"> The Bluetooth LE advertisement
	///   object. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="CwclBluetoothLeAdvertisement" />
	int Add(CwclBluetoothLeAdvertisement* const Advertisement);
	/// <summary> Clears the advertisements list. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Clear();
	/// <summary> Deletes the Bluetooth LE advertisement from the advertisements
	///   list. </summary>
	/// <param name="Index"> The advertisement index. The <c>Index</c> must be
	///   in range between <c>0</c> and <c>Count - 1</c>. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Delete(const size_t Index);
	
	/// <summary> Starts advertising. </summary>
	/// <param name="Radio"> The <see cref="CwclBluetoothRadio" /> object used
	///   to communicate with a remote Bluetooth device. </param>
	/// <param name="Interval"> An advertising interval in 0.625 ms
    ///   units. The value must be in range between
    ///   <see cref="WCL_BLE_MIN_ADVERTISING_INTERVAL" /> and
    ///   <see cref="WCL_BLE_MAX_ADVERTISING_INTERVAL" />. The default value is
    ///   <see cref="WCL_BLE_DEFAULT_ADVERTISING_INTERVAL" />. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers only. </remarks>
	/// <seealso cref="CwclBluetoothRadio" />
	/// <seealso cref="WCL_BLE_MIN_ADVERTISING_INTERVAL" />
    /// <seealso cref="WCL_BLE_MAX_ADVERTISING_INTERVAL" />
    /// <seealso cref="WCL_BLE_DEFAULT_ADVERTISING_INTERVAL" />
	int Start(CwclBluetoothRadio* const Radio,
		const unsigned short Interval = WCL_BLE_DEFAULT_ADVERTISING_INTERVAL);
	/// <summary> Stops advertising. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This feature is supported on Windows 10 with the Microsoft
	///   Bluetooth drivers only. </remarks>
	int Stop();
	
	/// <summary> Gets the Bluetooth LE advertisement object by its index. </summary>
	/// <param name="Index"> The advertisement index. The <c>Index</c> must be
	///   in range between <c>0</c> and <c>Count - 1</c>. </param>
	/// <returns> The Bluetooth LE advertisement object. </returns>
	/// <seealso cref="CwclBluetoothLeAdvertisement" />
	/// <exception cref="wclEInvalidArgument"></exception>
	CwclBluetoothLeAdvertisement* GetAdvertisements(const size_t Index) const;
	/// <summary> Gets the Bluetooth LE advertisement object by its index. </summary>
	/// <value> The Bluetooth LE advertisement object. </value>
	/// <seealso cref="CwclBluetoothLeAdvertisement" />
	/// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetAdvertisements)) CwclBluetoothLeAdvertisement* Advertisements[];

	/// <summary> Gets Advertiser state. </summary>
	/// <returns> <c>True</c> if the Bluetooth LE advertising is running. </returns>
	bool GetAdvertising() const;
	/// <summary> Gets Advertiser state. </summary>
	/// <value> <c>True</c> if the Bluetooth LE advertising is running. </value>
	__declspec(property(get = GetAdvertising)) bool Advertising;

	/// <summary> Gets the advertisements count. </summary>
	/// <returns> The number of the Bluetooth LE advertisements. </returns>
	size_t GetCount() const;
	/// <summary> Gets the advertisements count. </summary>
	/// <value> The number of the Bluetooth LE advertisements. </value>
	__declspec(property(get = GetCount)) size_t Count;

	/// <summary> Gets the advertising interval. </summary>
	/// <returns> The advertising interval in 0.625ms units. </returns>
    unsigned short GetInterval() const;
	/// <summary> Gets the advertising interval. </summary>
	/// <value> The advertising interval in 0.625ms units. </value>
	__declspec(property(get = GetInterval)) unsigned short Interval;

	/// <summary> Gets the advertiser owner. </summary>
	/// <returns> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the advertiser owner. </summary>
	/// <value> The <see cref="CwclBluetoothRadio" /> object owns the
	///   connection. </value>
	/// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/* Extended advertisement properties. */
	
	/// <summary> Specifies whether or not the device address is included in the
	///   advertisement header. By default, the address is included. </summary>
	/// <returns> The value indicates whether the device address is hidden. </returns>
	bool GetAnonymous() const;
	/// <summary> Specifies whether or not the device address is included in the
	///   advertisement header. By default, the address is included. </summary>
	/// <param name="value"> Indicates whether the device address is hidden. The default
	///   value is <c>False</c>, indicating that the address is
	///   included. </param>
	/// <remarks> <para> The Extended Advertising format must be enabled by
	///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
	///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
	///   value of this property is ignored. </para>
	///   <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetAnonymous(const bool value);
	/// <summary> Specifies whether or not the device address is included in the
    ///   advertisement header. By default, the address is included. </summary>
    /// <value> Indicates whether the device address is hidden. The default
    ///   value is <c>False</c>, indicating that the address is
    ///   included. </value>
    /// <remarks> <para> The Extended Advertising format must be enabled by
    ///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
    ///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
    ///   value of this property is ignored. </para>
    ///   <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetAnonymous, put = SetAnonymous)) bool Anonymous;

	/// <summary> Specifies whether the transmit power level is included in
	///   the advertisement header. </summary>
	/// <returns> The value indicates whether the transmit power level is
	///   included. </returns>
	bool GetIncludeTxRssi() const;
	/// <summary> Specifies whether the transmit power level is included in
	///   the advertisement header. </summary>
	/// <param name="value"> Indicates whether the transmit power level is included.
	///   The default value is <c>False</c>. </param>
	/// <remarks> <para> The Extended Advertising format must be enabled by
	///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
	///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
	///   value of this property is ignored. </para>
	///   <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetIncludeTxRssi(const bool value);
	/// <summary> Specifies whether the transmit power level is included in
    ///   the advertisement header. </summary>
    /// <value> Indicates whether the transmit power level is included. The
    ///   default value is <c>False</c>. </value>
    /// <remarks> <para> The Extended Advertising format must be enabled by
    ///   setting the <c>UseExtendedAdvertisement</c> to <c>True</c> to use this
    ///   property. If the <c>UseExtendedAdvertisement</c> is <c>False</c> the
    ///   value of this property is ignored. </para>
    ///   <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetIncludeTxRssi, put = SetIncludeTxRssi))
		bool IncludeTxRssi;

	/// <summary> If specified, requests that the radio use the indicated
	///   transmit power level for the advertisement. </summary>
	/// <returns> The requested power level in dDm at range between -100
	///   dBm and +20 for the radio transmission. </returns>
	char GetPreferredTxRssi() const;
	/// <summary> If specified, requests that the radio use the indicated
	///   transmit power level for the advertisement. </summary>
	/// <param name="value"> The requested power level in dDm at range between -100
	///   dBm and +20 for the radio transmission. The default is -127 indicating
	///   that this feature is disabled. If the parameter is out of range the
	///   <see cref="wclEInvalidArgument" /> exception raises. </param>
	/// <remarks> <para> Enabling the Extended Advertising format is necessary
	///   to enable several other related properties. </para>
	///  <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEInvalidArgument"></exception>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetPreferredTxRssi(const char value);
	/// <summary> If specified, requests that the radio use the indicated
    ///   transmit power level for the advertisement. </summary>
    /// <value> The requested power level in dDm at range between -100
    ///   dBm and +20 for the radio transmission. The default is -127 indicating
    ///   that this feature is disabled. If the parameter is out of range the
    ///   <see cref="wclEInvalidArgument" /> exception raises.</value>
    /// <remarks> <para> Enabling the Extended Advertising format is necessary
    ///   to enable several other related properties. </para>
    ///  <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEInvalidArgument"></exception>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetPreferredTxRssi, put = SetPreferredTxRssi))
		char PreferredTxRssi;

	/// <summary> Specifies that the advertisement publisher should use the
	///   Extended Advertising format. </summary>
	/// <returns> The value indicates whether or not the Extended Advertising format
	///   should be used. </returns>
	bool GetUseExtendedAdvertisement() const;
	/// <summary> Specifies that the advertisement publisher should use the
	///   Extended Advertising format. </summary>
	/// <param name="value"> Indicates whether or not the Extended Advertising format
	///   should be used. The default value is <c>False</c>. </param>
	/// <remarks> <para> Enabling the Extended Advertising format is necessary
	///   to enable several other related properties. </para>
	///  <para> If the advertiser is running and an application changes the
	///   property the <see cref="wclEBluetoothLeBeacon" /> exception
	///   raises. </para> </remarks>
	/// <exception cref="wclEBluetoothLeBeacon"></exception>
	void SetUseExtendedAdvertisement(const bool value);
	/// <summary> Specifies that the advertisement publisher should use the
    ///   Extended Advertising format. </summary>
    /// <value> Indicates whether or not the Extended Advertising format should
    ///   be used. The default value is <c>False</c>. </value>
    /// <remarks> <para> Enabling the Extended Advertising format is necessary
    ///   to enable several other related properties. </para>
    ///  <para> If the advertiser is running and an application changes the
    ///   property the <see cref="wclEBluetoothLeBeacon" /> exception
    ///   raises. </para> </remarks>
    /// <exception cref="wclEBluetoothLeBeacon"></exception>
	__declspec(property(get = GetUseExtendedAdvertisement, put = SetUseExtendedAdvertisement))
		bool UseExtendedAdvertisement;

	/// <summary> The event fires when the advertising started. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(OnStarted);
    /// <summary> The event fires when the advertising stopped. </summary>
    /// <param name="Sender"> The object that initiated the event. </param>
    wclNotifyEvent(OnStopped);
};

/// <summary> The class provides methods to communicate with Wii Remote
///   controller. </summary>
class CwclWiiRemoteClient : public CwclBluetoothComponent
{
	DISABLE_COPY(CwclWiiRemoteClient);
	
private:
	bool			FActive;
	__int64			FAddress;
	unsigned long	FTimeout;
	
	CwclWiiRemoteClientConnection* FClient;
	
	/* Client events. */
	
	void ClientAccelChanged(void* Sender, const wclWiiRemoteAccel& Accel);
	void ClientBalanceBoardChanged(void* Sender, const wclWiiRemoteBalanceBoard& Board);
	void ClientButtonsChanged(void* Sender, const wclWiiRemoteButtons& Buttons);
	void ClientClassicControllerChanged(void* Sender,
		const wclWiiRemoteClassicController& Controller);
	void ClientConnect(void* Sender, const int Error);
	void ClientDisconnect(void* Sender, const int Reason);
	void ClientDrumsChanged(void* Sender, const wclWiiRemoteDrums& Drums);
	void ClientExtensionAttached(void* Sender);
	void ClientExtensionDetached(void* Sender);
	void ClientGuitarChanged(void* Sender, const wclWiiRemoteGuitar& Guitar);
	void ClientIrChanged(void* Sender, const wclWiiRemoteIrSensors& Ir);
	void ClientNunchukChanged(void* Sender, const wclWiiRemoteNunchuk& Nunchuk);
	void ClientStatusChanged(void* Sender, const double Batt, const wclWiiRemoteLeds& Leds);
	
protected:
	/// <summary> Fire the <c>OnAccelChanged</c> event. </summary>
	/// <param name="Accel"> The current accelerometer data. </param>
	/// <seealso cref="wclWiiRemoteAccel" />
	virtual void DoAccelChanged(const wclWiiRemoteAccel& Accel);
	/// <summary> Fires the <c>OnBalanceBoardChanged</c> event </summary>
	/// <param name="Board"> The new Balance Board extension
	///   state. </param>
	/// <seealso cref="wclWiiRemoteBalanceBoard" />
	virtual void DoBalanceBoardChanged(const wclWiiRemoteBalanceBoard& Board);
	/// <summary> Fires the <c>OnButtonsChanged</c> event. </summary>
	/// <param name="Buttons"> The new buttons state. </param>
	/// <seealso cref="wclWiiRemoteButtons" />
	virtual void DoButtonsChanged(const wclWiiRemoteButtons& Buttons);
	/// <summary> Fires the <c>OnClassicControllerChanged</c> event. </summary>
	/// <param name="Controller"> The current state of the Wii Remote Classic
	///   Controller extension. </param>
	/// <seealso cref="wclWiiRemoteClassicController" />
	virtual void DoClassicControllerChanged(const wclWiiRemoteClassicController& Controller);
	/// <summary> Fires the <c>OnConnect</c> event. </summary>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
	virtual void DoConnect(const int Error);
	/// <summary> Fires the <c>OnDisconnect</c> event. </summary>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	virtual void DoDisconnect(const int Reason);
	/// <summary> Fires the <c>OnDrumsChanged</c> event. </summary>
	/// <param name="Drums"> The current state of the Drums extension. </param>
	/// <seealso cref="wclWiiRemoteDrums" />
	virtual void DoDrumsChanged(const wclWiiRemoteDrums& Drums);
	/// <summary> Fires the <c>OnExtensionAttached</c> event. </summary>
	virtual void DoExtensionAttached();
	/// <summary> Fires the <c>OnExtensionDetached</c> event. </summary>
	virtual void DoExtensionDetached();
	/// <summary> Fires the <c>OnGuitarChanged</c> event. </summary>
	/// <param name="Guitar"> The current Guitar extension state. </param>
	/// <seealso cref="wclWiiRemoteGuitar" />
	virtual void DoGuitarChanged(const wclWiiRemoteGuitar& Guitar);
	/// <summary> Fires the <c>OnIrChanged</c> event. </summary>
	/// <param name="Ir"> The IR sensor data. </param>
	/// <seealso cref="wclWiiRemoteIrSensors" />
	virtual void DoIrChanged(const wclWiiRemoteIrSensors& Ir);
	/// <summary> Fires the <c>OnNunchukChanged</c> event. </summary>
	/// <param name="Nunchuk"> The current Nunchuk extension state. </param>
	/// <seealso cref="wclWiiRemoteNunchuk" />
	virtual void DoNunchukChanged(const wclWiiRemoteNunchuk& Nunchuk);
	/// <summary> Fires the <c>OnStatusChanged</c> event. </summary>
	/// <param name="Batt"> The WeDo Remote battery level. </param>
	/// <param name="Leds"> The We Do Remote LEDs state. </param>
	/// <seealso cref="wclWiiRemoteLeds" />
	virtual void DoStatusChanged(const double Batt, const wclWiiRemoteLeds& Leds);
	
public:
	/// <summary> Creates new Wii Remote client component. </summary>
	CwclWiiRemoteClient();
	/// <summary> Frees the component. </summary>
    virtual ~CwclWiiRemoteClient();
	
	/// <summary> Starts connecting to a Wii Remote device. </summary>
	/// <param name="Radio"> The <see cref="TwclBluetoothRadio" /> object
	///   that handles the connection. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	int Connect(CwclBluetoothRadio* const Radio);
	/// <summary> Disconnects from the Wii Remote. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Disconnect();
	
	/// <summary> Requests the Wii Remote status. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <remarks> This is asynchronous method. When operation completes the
	///   <c>OnStatusChanged</c> event fires. </remarks>
	int GetStatus();
	
	/// <summary> Changes the Wii Remote LEDs state. </summary>
	/// <param name="Leds"> The new LEDs state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclWiiRemoteLeds" />
	int SetLeds(const wclWiiRemoteLeds& Leds);
	/// <summary> Changes the Wii Remote LEDs state. </summary>
	/// <param name="Led1"> The new LED 1 state. </param>
	/// <param name="Led2"> The new LED 2 state. </param>
	/// <param name="Led3"> The new LED 3 state. </param>
	/// <param name="Led4"> The new LED 4 state. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetLeds(const bool Led1, const bool Led2, const bool Led3, const bool Led4);
	/// <summary> Turns the Rumble On and Off. </summary>
	/// <param name="TurnOn"> Set to <c>True</c> to turn the Rumble On. Set
	///   to <c>False</c> to turn the Rumble Off. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int SetRumble(const bool TurnOn);
	
	/// <summary> Enables accelerometer. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int EnableAccel();
	/// <summary> Disables accelerometer. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int DisableAccel();
	
	/// <summary> Sets IR IR sensor sensitivity (and turns it ON or
	///   OFF). </summary>
	/// <param name="Sensitivity"> The IR sensor sensitivity. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	int SetIrSensitivity(const wclWiiRemoteIrSensitivity& Sensitivity);

	/// <summary> Gets the current accelerometer status. </summary>
	/// <returns> <c>True</c> if the accelerometer is enabled. <c>False</c>
    ///   otherwise. </returns>
	bool GetAccelEnabled() const;
	/// <summary> Gets the current accelerometer status. </summary>
	/// <value> <c>True</c> if the accelerometer is enabled. <c>False</c>
    ///   otherwise. </value>
	__declspec(property(get = GetAccelEnabled)) bool AccelEnabled;

	/// <summary> Gets the current connected extension type. </summary>
	/// <returns> The currently connected extension. </returns>
	/// <seealso cref="wclWiiRemoteExtension " />
	wclWiiRemoteExtension GetExtension() const;
	/// <summary> Gets the current connected extension type. </summary>
	/// <value> The currently connected extension. </value>
	/// <seealso cref="wclWiiRemoteExtension " />
	__declspec(property(get = GetExtension)) wclWiiRemoteExtension Extension;

	/// <summary> Gets the current IR sensor mode. </summary>
	/// <returns> The IR sensor mode. </returns>
    /// <seealso cref="wclWiiRemoteIrMode" />
	wclWiiRemoteIrMode GetIrMode() const;
	/// <summary> Gets the current IR sensor mode. </summary>
	/// <value> The IR sensor mode. </value>
    /// <seealso cref="wclWiiRemoteIrMode" />
	__declspec(property(get = GetIrMode)) wclWiiRemoteIrMode IrMode;

	/// <summary> Gets the current IR sensor sensitivity. </summary>
	/// <returns> The IR sensor sensitivity. </returns>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	wclWiiRemoteIrSensitivity GetIrSensitivity() const;
	/// <summary> Gets the current IR sensor sensitivity. </summary>
	/// <value> The IR sensor sensitivity. </value>
	/// <seealso cref="wclWiiRemoteIrSensitivity" />
	__declspec(property(get = GetIrSensitivity)) wclWiiRemoteIrSensitivity IrSensitivity;

	/// <summary> Gets the current LEDs state. </summary>
	/// <returns> The LEDs state. </returns>
    /// <seealso cref="wclWiiRemoteLeds " />
	wclWiiRemoteLeds GetLeds() const;
	/// <summary> Gets the current LEDs state. </summary>
	/// <value> The LEDs state. </value>
    /// <seealso cref="wclWiiRemoteLeds " />
	__declspec(property(get = GetLeds)) wclWiiRemoteLeds Leds;

	/// <summary> Gets the radio object used for connection. </summary>
	/// <returns> The <see cref="TwclBluetoothRadio" /> object. </returns>
	/// <seealso cref="CwclBluetoothRadio" />
	CwclBluetoothRadio* GetRadio() const;
	/// <summary> Gets the radio object used for connection. </summary>
	/// <value> The <see cref="TwclBluetoothRadio" /> object. </value>
	/// <seealso cref="CwclBluetoothRadio" />
	__declspec(property(get = GetRadio)) CwclBluetoothRadio* Radio;

	/// <summary> Gets the current Rumble status. </summary>
	/// <returns> <c>True</c> if the Rumble is turned ON. </returns>
	bool GetRumble() const;
	/// <summary> Gets the current Rumble status. </summary>
	/// <value> <c>True</c> if the Rumble is turned ON. </value>
	__declspec(property(get = GetRumble)) bool Rumble;

	/// <summary> Gets the current client state. </summary>
	/// <returns> The client state. </returns>
	/// <seealso cref="wclClientState" />
    wclClientState GetState() const;
	/// <summary> Gets the current client state. </summary>
	/// <value> The client state. </value>
	/// <seealso cref="wclClientState" />
	__declspec(property(get = GetState)) wclClientState State;
	
	/// <summary> Gets a target WiiRemote device's MAC
	///   address. </summary>
	/// <returns> The Bluetooth MAC address. </returns>
    __int64 GetAddress() const;
	/// <summary> Sets a target WiiRemote device's MAC address. </summary>
	/// <param name="Address"> The Bluetooth MAC address. </param>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
    void SetAddress(const __int64 Address);
	/// <summary> Gets and sets a target WiiRemote device's MAC
    ///   address. </summary>
    /// <value> The Bluetooth MAC address. </value>
    /// <remarks> If an application changes the property when connection
    ///   is active the <see cref="wclEBluetoothClient" /> exception
    ///   raises. </remarks>
    /// <exception cref="wclEBluetoothClient"></exception>
	__declspec(property(get = GetAddress, put = SetAddress)) __int64 Address;
	
	/// <summary> Gets the connect timeout value. </summary>
    /// <returns> The connect timeout value in milliseconds. </returns>s>
    /// <exception cref="wclEClientActive"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	unsigned long GetTimeout() const;
	/// <summary> Sets the connect timeout value. </summary>
	/// <param name="Timeout"> The connect timeout value in milliseconds. </param>
	/// <remarks> If an application changes the property when client is
	///   connected the <see cref="wclEClientActive" /> exception
	///   raises. If new value of the <c>Timeout</c> is <c>0</c> the
	///   <see cref="wclEInvalidArgument" /> exception raises. </remarks>
	/// <exception cref="wclEClientActive"></exception>
	/// <exception cref="wclEInvalidArgument"></exception>
	void SetTimeout(const unsigned long Timeout);
	/// <summary> Gets and sets the connect timeout value. </summary>
    /// <value> The connect timeout value in milliseconds. </value>
    /// <remarks> If an application changes the property when client is
    ///   connected the <see cref="wclEClientActive" /> exception
    ///   raises. If new value of the <c>Timeout</c> is <c>0</c> the
    ///   <see cref="wclEInvalidArgument" /> exception raises. </remarks>
    /// <exception cref="wclEClientActive"></exception>
    /// <exception cref="wclEInvalidArgument"></exception>
	__declspec(property(get = GetTimeout, put = SetTimeout)) unsigned long Timeout;

	/// <summary> The event fires when the accelerometer state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Accel"> The current accelerometer data. </param>
	/// <seealso cref="wclWiiRemoteAccel" />
	wclWiiRemoteAccelChangedEvent(OnAccelChanged);
	/// <summary> The event fires when the stat eof the Balance Board extension
	///   has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Board"> The new Balance Board extension
	///   state. </param>
	/// <seealso cref="wclWiiRemoteBalanceBoard" />
	wclWiiRemoteBalanceBoardChangedEvent(OnBalanceBoardChanged);
	/// <summary> The event fires when the buttons state of the Wii Remote
	///   controller has been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Buttons"> The current state of the Wii Remote controller
	///   buttons. </param>
	/// <seealso cref="wclWiiRemoteButtons" />
	wclWiiRemoteButtonsChangedEvent(OnButtonsChanged);
	/// <summary> The event fires when a Classic Controller extension state has
	///   been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Controller"> The current state of the Wii Remote Classic
	///   Controller extension. </param>
	/// <seealso cref="wclWiiRemoteClassicController" />
	wclWiiRemoteClassicControllerChangedEvent(OnClassicControllerChanged);
	/// <summary> The event fires when a connection to a remote device
	///   has been completed (with or without success). </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
    /// <remarks> If the <c>Error</c> parameter of the event is not
    ///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
    ///   method again from inside the event handler. </remarks>
	wclClientConnectionConnectEvent(OnConnect);
	/// <summary> The event fires when the remote connected device has been
	///   disconnected. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	wclClientConnectionDisconnectEvent(OnDisconnect);
	/// <summary> The event fires when the Drums extension state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Drums"> The current state of the Drums extension. </param>
	/// <seealso cref="wclWiiRemoteDrums" />
	wclWiiRemoteDrumsChangedEvent(OnDrumsChanged);
	/// <summary> The event fires when the extension is attached. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnExtensionAttached);
	/// <summary> The event fires when the extension has been
	///   detached. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnExtensionDetached);
	/// <summary> The event fires when the Guitar extension state has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Guitar"> The current Guitar extension state. </param>
	/// <seealso cref="wclWiiRemoteGuitar" />
	wclWiiRemoteGuitarChangedEvent(OnGuitarChanged);
	/// <summary> The event fires when the IR sensor data has been
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Ir"> The IR sensor data. </param>
	/// <seealso cref="wclWiiRemoteIrSensors" />
	wclWiiRemoteIrChangedEvent(OnIrChanged);
	/// <summary> The event fires when the state of the Nunchuk extension has
	///   been changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Nunchuk"> The current Nunchuk extension state. </param>
	/// <seealso cref="wclWiiRemoteNunchuk" />
	wclWiiRemoteNunchukChangedEvent(OnNunchukChanged);
	/// <summary> The event fires when the WeDo Remote status
	///   changed. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Batt"> The WeDo Remote battery level. </param>
	/// <param name="Leds"> The We Do Remote LEDs state. </param>
	/// <seealso cref="wclWiiRemoteLeds" />
	wclWiiRemoteStatusChangedEvent(OnStatusChanged);
};

/// <summary> The Bluetooth LE packets sniffer. </summary>
class CwclBleSniffer
{
	DISABLE_COPY(CwclBleSniffer);
	
private:
	unsigned char			FChannel;
	tstring					FDevicePath;
	HANDLE					FInitEvent;
	int						FInitResult;
	CwclMessageReceiver*	FReceiver;
	HANDLE					FTermEvent;
	HANDLE					FThread;

    tstring FindDevice();

	__int64 DecodeAddress(const unsigned char* const Pdu, const unsigned char Ndx,
		const unsigned char Len) const;

	/* Packet parsers. */

	// Advertising PDU parsers
	bool ParseConnectIndPdu(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const unsigned char* const Pdu, const unsigned char PduLen) const;
	bool ParseSingleAddrAdvertisingPdu(const unsigned char Id,
		const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const unsigned char* const Pdu, const unsigned char PduLen) const;
	bool ParseTwoAddrAdvertisingPdu(const unsigned char Id,
		const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const unsigned char* const Pdu, const unsigned char PduLen) const;
	bool ParseAdvertisingPacket(const wclBluetoothLePacketHeader& Header,
		const unsigned char* const Payload, const unsigned short Len) const;

    bool ParseDataPacket(const wclBluetoothLePacketHeader& Header,
		const unsigned char* const Payload, const unsigned short Len) const;
	void ParsePacket(const unsigned char* const Packet,
		const unsigned short Size);

	static UINT __stdcall _SnifferThread(LPVOID Param);
	void SnifferThread();

protected:
	/// <summary> The method called when a new notification message
	///   received. </summary>
	/// <param name="Message"> A <see cref="CwclMessage" /> object
	///   represents a notification message. </param>
	/// <remarks> <para> This method is for internal use only. </para>
	///   <para> If a derived class overrides this method it must always call
	///   the inherited implementation first. </para> </remarks>
	/// <seealso cref="CwclMessage" />
	virtual void MessageReceived(const CwclMessage* const Message);
	
	/// <summary> Fires the <c>OnAdvDirectIndReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="TargetA"> The address of the device to which this PDU
	///   is addressed. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True).
	///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
	///   whether the target’s address in the <c>TargetA</c> parameter is
	///   public (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c>
	///   field in the <c>PduHeader</c> parameter is <c>True</c> if the
	///   advertiser supports the LE Channel Selection Algorithm #2
	///   feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoAdvDirectIndReceived(
		const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 AdvA, const __int64 TargetA);
	/// <summary> Fires the <c>OnAdvIndReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). The
	///   <c>ChSel</c> field in the <c>PduHeader</c> parameter is <c>True</c>
	///   if the advertiser supports the LE Channel Selection Algorithm #2
	///   feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoAdvIndReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 AdvA, const unsigned char* const AdvData,
		const unsigned char AdvDataLen);
	/// <summary> Fires the <c>OnAdvNonConnIndReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoAdvNonConnIndReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 AdvA, const unsigned char* const AdvData,
		const unsigned char AdvDataLen);
	/// <summary> Fires the <c>OnAdvScanIndReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoAdvScanIndReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 AdvA, const unsigned char* const AdvData,
		const unsigned char AdvDataLen);
	/// <summary> Fires the <c>OnConnectIndReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="InitA"> The Initiator’s device address. </param>
	/// <param name="AdvA"> The advertiser’s device address. </param>
	/// <param name="LlData"> The Link Layer data. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>InitA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). The
	///   <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates whether
	///   the advertiser’s device address in the <c>AdvA</c> parameter is public
	///   (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c> field in
	///   the <c>PduHeader</c> parameter is <c>True</c> if the advertiser
	///   supports the LE Channel Selection Algorithm #2 feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	/// <seealso cref="wclBleSnifferLlData" />
	virtual void DoConnectIndReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 InitA, const __int64 AdvA, const wclBleSnifferLlData& LlData);
	/// <summary> Fires the <c>OnScanReqReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="ScanA"> The scanner's address. </param>
	/// <param name="AdvA"> The address of the device to which this PDU
	///   is addressed. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the scanner’s address in the <c>ScanA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True).
	///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
	///   whether the target’s address in the <c>AdvA</c> parameter is
	///   public (RxAdd = False) or random (RxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoScanReqReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 ScanA, const __int64 AdvA);
	/// <summary> Fires the <c>OnScanRspReceived</c> event. </summary>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="ScanRspData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="ScanRspDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random
	///   (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	virtual void DoScanRspReceived(const wclBluetoothLeAdvertisingPduHeader& PduHeader,
		const __int64 AdvA, const unsigned char* const ScanRspData,
		const unsigned char ScanRspDataLen);
	/// <summary> Fires the <c>OnRawPacketReceived</c> event. </summary>
	/// <param name="Header"> The Bluetooth LE packet header. </param>
	/// <param name="Payload"> The pointer to the packet's payload raw bytes.
	///   The pointer is valid only inside an event handler. If an application
	///   needs to use the data outside the event handler it must copy the
	///   payload. </param>
	/// <param name="Size"> The payload size (length) in bytes. </param>
	/// <seealso cref="wclBluetoothLePacketHeader" />
	virtual void DoRawPacketReceived(const wclBluetoothLePacketHeader& Header,
		const unsigned char* const Payload, const unsigned short Size);
	/// <summary> Fires the <c>OnStarted</c> event. </summary>
	virtual void DoStarted();
	/// <summary> Fires the <c>OnStopped</c> event. </summary>
	virtual void DoStopped();
	
public:
	/// <summary> Creates new BLE sniffer component. </summary>
	CwclBleSniffer();
	/// <summary> Frees the component. </summary>
	virtual ~CwclBleSniffer();
	
	/// <summary> Starts capturing the BLE packets. </summary>
	/// <param name="DevicePath"> The device's path. If the parameter is an
	///   empty string first found device will be used. </param>
	/// <param name="Channel"> The channel number. Only channels 37, 38 and 39
	///   are supported. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Start(const tstring& DevicePath, const unsigned char Channel);
	/// <summary> Starts capturing the BLE packets. </summary>
	/// <param name="Channel"> The channel number. Only channels 37, 38 and 39
	///   are supported. </param>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Start(const unsigned char Channel);
	/// <summary> Stops capturing the BLE packets. </summary>
	/// <returns> If the function succeed the return value is
	///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
	///   the WCL error codes. </returns>
	int Stop();
	
	/// <summary> Gets the sniffer's status. </summary>
	/// <returns> <c>True</c> if the sniffer is running. <c>False</c>
	///   otherwise. </returns>
	bool GetActive() const;
	/// <summary> Gets the sniffer's status. </summary>
	/// <value> <c>True</c> if the sniffer is running. <c>False</c>
	///   otherwise. </value>
	__declspec(property(get = GetActive)) bool Active;

	/// <summary> Gets the radio channel. </summary>
	/// <returns> The channel number. </returns>
	unsigned char GetChannel() const;
	/// <summary> Gets the radio channel. </summary>
	/// <value> The channel number. </value>
	__declspec(property(get = GetChannel)) unsigned char Channel;

	/// <summary> Gets the current device's path. </summary>
	/// <returns> The device's path. </returns>
    tstring GetDevicePath() const;
	/// <summary> Gets the current device's path. </summary>
	/// <value> The device's path. </value>
	__declspec(property(get = GetDevicePath)) tstring DevicePath;

	/// <summary> The event fires when the <c>ADV_DIRECT_IND</c> PDU
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="TargetA"> The address of the device to which this PDU
	///   is addressed. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True).
	///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
	///   whether the target’s address in the <c>TargetA</c> parameter is
	///   public (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c> field
	///   in the <c>PduHeader</c> parameter is <c>True</c> if the advertiser
	///   supports the LE Channel Selection Algorithm #2 feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
    wclBleSnifferAdvDirectIndReceivedEvent(OnAdvDirectIndReceived);
	/// <summary> The event fires when the <c>ADV_IND</c> PDU
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). The
	///   <c>ChSel</c> field in the <c>PduHeader</c> parameter is <c>True</c>
	///   if the advertiser supports the LE Channel Selection Algorithm #2
	///   feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	wclBleSnifferAdvIndReceivedEvent(OnAdvIndReceived);
	/// <summary> The event fires when the <c>ADV_NONCONN_IND</c> PDU
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
    wclBleSnifferAdvNonConnIndReceivedEvent(OnAdvNonConnIndReceived);
	/// <summary> The event fires when the <c>ADV_SCAN_IND</c> PDU
	///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="AdvData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="AdvDataLen"> The advertisement data length in bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
    wclBleSnifferAdvScanIndReceivedEvent(OnAdvScanIndReceived);
	/// <summary> The event fires when the <c>CONNECT_IND</c> PDU
    ///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="InitA"> The Initiator’s device address. </param>
	/// <param name="AdvA"> The advertiser’s device address. </param>
	/// <param name="LlData"> The Link Layer data. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>InitA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). The
	///   <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates whether
	///   the advertiser’s device address in the <c>AdvA</c> parameter is public
	///   (RxAdd = False) or random (RxAdd = True). The <c>ChSel</c> field in the
	///   <c>PduHeader</c> parameter is <c>True</c> if the advertiser supports the
	///   LE Channel Selection Algorithm #2 feature. </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	/// <seealso cref="wclBleSnifferLlData" />
	wclBleSnifferConnectIndReceivedEvent(OnConnectIndReceived);
	/// <summary> The event fires when the <c>SCAN_REQ</c> PDU
    ///   received. </summary>
    /// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="ScanA"> The scanner's address. </param>
	/// <param name="AdvA"> The address of the device to which this PDU
	///   is addressed. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the scanner’s address in the <c>ScanA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True).
	///   The <c>RxAdd</c> field of the <c>PduHeader</c> parameter indicates
	///   whether the target’s address in the <c>AdvA</c> parameter is
	///   public (RxAdd = False) or random (RxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
	wclBleSnifferScanReqReceivedEvent(OnScanReqReceived);
	/// <summary> The event fires when the <c>SCAN_RSP</c> PDU
    ///   received. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="PduHeader"> The PDU header. </param>
	/// <param name="AdvA"> The advertiser address. </param>
	/// <param name="ScanRspData"> The pointer to the advertisement data.
	///   Can be <c>NULL</c>. The pointer is valid only inside the event
	///   handler. </param>
	/// <param name="ScanRspDataLen"> The advertisement data length in
	///   bytes. </param>
	/// <remarks> The <c>TxAdd</c> field of the <c>PduHeader</c> parameter
	///   indicates whether the advertiser’s address in the <c>AdvA</c>
	///   parameter is public (TxAdd = False) or random (TxAdd = True). </remarks>
	/// <seealso cref="wclBluetoothLeAdvertisingPduHeader" />
    wclBleSnifferScanRspReceivedEvent(OnScanRspReceived);
    /// <summary> The event fires when a Bluetooth LE packet
    ///   captured. </summary>
	/// <param name="Sender"> The object initiates the event. </param>
	/// <param name="Header"> The Bluetooth LE packet header. </param>
	/// <param name="Payload"> The pointer to the packet's payload raw bytes.
	///   The pointer is valid only inside an event handler. If an application
	///   needs to use the data outside the event handler it must copy the
	///   payload. </param>
	/// <param name="Size"> The payload size (length) in bytes. </param>
	/// <seealso cref="wclBluetoothLePacketHeader" />
	wclBleSnifferRawPacketReceivedEvent(OnRawPacketReceived);
	/// <summary> The event fires when the Sniffer was successfully
	///   started. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStarted);
    /// <summary> The event fires when the Sniffer was successfully
	///   stopped. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	wclNotifyEvent(OnStopped);
};

}