//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "wclBluetooth"
#pragma resource "*.dfm"

TfmMain *fmMain;
//---------------------------------------------------------------------------
__fastcall TfmMain::TfmMain(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btClearEventsClick(TObject *Sender)
{
  lvEvents->Items->Clear();        
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::TraceEvent(TwclBluetoothRadio* Radio,
  String Event, String Parameter, String Value)
{
  TListItem* Item = lvEvents->Items->Add();

  if (Radio != NULL)
    Item->Caption = Radio->ApiName;
  else
    Item->Caption = "";

  Item->SubItems->Add(Event);
  Item->SubItems->Add(Parameter);
  Item->SubItems->Add(Value);

  lvEvents->Selected = Item;
  Item->MakeVisible(false);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormDestroy(TObject *Sender)
{
  wclBluetoothManager->Close();
  FPowerMonitor->Close();
  FPowerMonitor->Free();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::ClearRadios()
{
  lvRadios->Items->Clear();
  ClearDevices();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::RefreshRadio(TListItem* Item)
{
  TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

  Item->Caption = Radio->ApiName;
  Item->SubItems->Strings[0] = BoolToStr(Radio->Available, true);

  __int64 Address = 0;
  int Res = Radio->GetAddress(Address);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[1] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[1] = IntToHex(Address, 12);

  bool BoolVal = false;
  Res = Radio->GetConnectable(BoolVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[2] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[2] = BoolToStr(BoolVal, true);

  Res = Radio->GetDiscoverable(BoolVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[3] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[3] = BoolToStr(BoolVal, true);

  unsigned char ByteVal = 0;
  unsigned short WordVal = 0;
  Res = Radio->GetHciVersion(ByteVal, WordVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[4] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[4] = IntToStr(ByteVal) + '.' + IntToStr(WordVal);

  Res = Radio->GetLmpVersion(ByteVal, WordVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[5] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[5] = IntToStr(ByteVal) + '.' + IntToStr(WordVal);

  Res = Radio->GetManufacturer(WordVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[6] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[6] = IntToStr(WordVal);

  String StrVal = "";
  Res = Radio->GetName(StrVal);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[7] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[7] = StrVal;

  unsigned int Cod = 0;
  Res = Radio->GetCod(Cod);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[8] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[8] = "0x" + IntToHex((int)Cod, 8);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btRefreshRadioClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
    RefreshRadio(lvRadios->Selected);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btOpenClick(TObject *Sender)
{
  int Res = wclBluetoothManager->Open(cbHandlePairing->Checked);
  if (Res != WCL_E_SUCCESS)
    ShowError(Res);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btCloseClick(TObject *Sender)
{
  int Res = wclBluetoothManager->Close();
  if (Res != WCL_E_SUCCESS)
    ShowError(Res);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::ShowError(int Error)
{
  MessageDlg("Error: 0x" + IntToHex(Error, 8), mtError,
    TMsgDlgButtons() << mbOK, 0);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btSetConnectableClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TModalResult Mr = MessageDlg("[YES] - turn connectable ON, [NO] - turn connectable OFF",
      mtConfirmation, mbYesNoCancel, 0);
    if (Mr != mrCancel)
    {
      TListItem* Item = lvRadios->Selected;
      TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

      int Res = Radio->SetConnectable(Mr == mrYes);
      if (Res != WCL_E_SUCCESS)
        ShowError(Res);

      RefreshRadio(Item);
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btSetDiscoverableClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TModalResult Mr = MessageDlg("[YES] - turn discoverable ON, [NO] - turn discoverable OFF",
      mtConfirmation, mbYesNoCancel, 0);
    if (Mr != mrCancel)
    {
      TListItem* Item = lvRadios->Selected;
      TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

      int Res = Radio->SetDiscoverable(Mr == mrYes);
      if (Res != WCL_E_SUCCESS)
        ShowError(Res);

      RefreshRadio(Item);
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btSetNameClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    int Res = Radio->SetName(edName->Text);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    RefreshRadio(Item);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btEnumPairedClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    ClearDevices();

    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    TwclBluetoothAddresses Devices;
    int Res = Radio->EnumPairedDevices(Devices);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    else
    {
      for (int i = 0; i < Devices.Length; i++)
        AddDevice(Radio, Devices[i]);

      RefreshDevices();
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::ClearDevices()
{
  lvDevices->Items->Clear();
  ClearServices();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::RefreshDevice(TListItem* Item)
{
  TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
  __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

  unsigned int Cod = 0;
  int Res = Radio->GetRemoteCod(Address, Cod);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[1] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[1] = IntToHex((int)Cod, 8);

  TwclBluetoothDeviceType DevType;
  Res = Radio->GetRemoteDeviceType(Address, DevType);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[2] = "Error: 0x" + IntToHex(Res, 8);

  else
  {
    switch (DevType)
    {
      case dtClassic:
        Item->SubItems->Strings[2] = "Classic";
        break;
      case dtBle:
        Item->SubItems->Strings[2] = "BLE";
        break;
      case dtMixed:
        Item->SubItems->Strings[2] = "Mixed";
        break;
      default:
        Item->SubItems->Strings[2] = "Unknown";
        break;
    }
  }

  String DevName = "";
  Res = Radio->GetRemoteName(Address, DevName);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[3] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[3] = DevName;

  bool Paired = false;
  Res = Radio->GetRemotePaired(Address, Paired);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[4] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[4] = BoolToStr(Paired, true);

  bool Connected = false;
  Res = Radio->GetRemoteConnectedStatus(Address, Connected);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[5] = "Error: 0x" + IntToHex(Res, 8);
  else
    Item->SubItems->Strings[5] = BoolToStr(Connected, true);

  TwclBluetoothAddressType AddrType;
  Res = Radio->GetRemoteAddressType(Address, AddrType);
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Strings[6] = "Error: 0x" + IntToHex(Res, 8);
  else
  {
    switch (AddrType)
    {
      case atClassic:
        Item->SubItems->Strings[6] = "Classic";
        break;
      case atPublic:
        Item->SubItems->Strings[6] = "LE Public";
        break;
      case atRandom:
        Item->SubItems->Strings[6] = "LE Random";
        break;
      case atUnspecified:
        Item->SubItems->Strings[6] = "Unspecified";
        break;
      default:
        Item->SubItems->Strings[6] = "Unknown";
        break;
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btRefreshDeviceClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
    RefreshDevice(lvDevices->Selected);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::ClearServices()
{
  lvServices->Items->Clear();
  ClearComPorts();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btEnumServicesClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    ClearServices();

    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    TwclBluetoothServices Services;
    int Res = Radio->EnumRemoteServices(Address, NULL, Services);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    else
    {
      for (int i = 0; i < Services.Length; i++)
      {
        Item = lvServices->Items->Add();

        Item->Caption = Radio->ApiName;
        Item->SubItems->Add(IntToHex(Address, 12));
        Item->SubItems->Add(IntToHex((int)Services[i].Handle, 8));
        Item->SubItems->Add(Sysutils::GUIDToString(Services[i].Uuid));
        Item->SubItems->Add(IntToStr(Services[i].Channel));
        Item->SubItems->Add(Services[i].Name);
        Item->SubItems->Add(Services[i].Comment);
      }
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btDiscoverClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    TwclBluetoothDiscoverKind Kind;
    if (cbDiscoveringMode->ItemIndex == 0)
      Kind = dkClassic;
    else
      Kind = dkBle;

    int Res = Radio->Discover(StrToInt(edTimeout->Text), Kind);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btTerminateClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    int Res = Radio->Terminate();
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::AddDevice(TwclBluetoothRadio* Radio, __int64 Address)
{
  TListItem* Item = lvDevices->Items->Add();
  Item->Data = Radio;

  Item->Caption = Radio->ApiName;
  Item->SubItems->Add(IntToHex(Address, 12));
  Item->SubItems->Add(""); // Class Of Device
  Item->SubItems->Add(""); // Device type
  Item->SubItems->Add(""); // Name
  Item->SubItems->Add(""); // Paired
  Item->SubItems->Add(""); // Connected
  Item->SubItems->Add(""); // Address type
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::RefreshDevices()
{
  for (int i = 0; i < lvDevices->Items->Count; i++)
    RefreshDevice(lvDevices->Items->Item[i]);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btUnpairClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    TwclBluetoothPairingMethod Method;
    switch (cbPairingMethod->ItemIndex)
    {
      case 1:
        Method = pmClassic;
        break;
      case 2:
        Method = pmLe;
        break;
      default:
	Method = Wclbluetooth::pmAuto;
        break;
    }

    int Res = Radio->RemoteUnpair(Address, Method);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    RefreshDevice(Item);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btPairClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
	__int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    TwclBluetoothPairingMethod Method;
    switch (cbPairingMethod->ItemIndex)
    {
      case 1:
        Method = pmClassic;
        break;
      case 2:
        Method = pmLe;
        break;
      default:
	Method = Wclbluetooth::pmAuto;
        break;
    }

    int Res = Radio->RemotePair(Address, Method);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btRSSIClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    signed char Rssi = 0;
    int Res = Radio->GetRemoteRssi(Address, Rssi);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
    else
    {
      MessageDlg("RSSI: " + IntToStr(Rssi) + "dB", mtInformation,
        TMsgDlgButtons() << mbOK, 0);
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btTurnOnClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    int Res = Radio->TurnOn();
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    RefreshRadio(Item);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btTurnOffClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    int Res = Radio->TurnOff();
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    RefreshRadio(Item);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerAfterOpen(TObject *Sender)
{
  TraceEvent(NULL, "AfterOpen", "HandlePairing",
    BoolToStr(wclBluetoothManager->HandlePairing, true));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerBeforeClose(TObject *Sender)
{
  TraceEvent(NULL, "BeforeClose", "", "");
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerAuthenticationCompleted(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const int Error)
{
  TraceEvent((TwclBluetoothRadio*)Radio, "AuthenticationCompleted", "Address",
    IntToHex(Address, 12));
  TraceEvent(NULL, "", "Error", "0x" + IntToHex(Error, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDeviceFound(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address)
{
  TraceEvent((TwclBluetoothRadio*)Radio, "DeviceFound", "Address",
    IntToHex(Address, 12));

  AddDevice((TwclBluetoothRadio*)Radio, Address);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDiscoveringCompleted(
      TObject *Sender, const TwclBluetoothRadio *Radio, const int Error)
{
  TraceEvent((TwclBluetoothRadio*)Radio, "DiscoveringCompleted", "Error",
    "0x" + IntToHex(Error, 8));

  RefreshDevices();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDiscoveringStarted(
      TObject *Sender, const TwclBluetoothRadio *Radio)
{
  ClearDevices();

  TraceEvent((TwclBluetoothRadio*)Radio, "DiscoveringStarted", "", "");
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerNumericComparison(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const DWORD Number, bool& Confirm)
{
  Confirm = true;

  TraceEvent((TwclBluetoothRadio*)Radio, "NumericComparison", "Address",
    IntToHex(Address, 12));
  TraceEvent(NULL, "", "Number", IntToStr((int)Number));
  TraceEvent(NULL, "", "Confirm", BoolToStr(Confirm, true));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPasskeyNotification(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const DWORD Passkey)
{
  TraceEvent((TwclBluetoothRadio*)Radio, "PasskeyNotification", "Address",
    IntToHex(Address, 12));
  TraceEvent(NULL, "", "Passkey", IntToStr((int)Passkey));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPasskeyRequest(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address,
      DWORD& Passkey)
{
  Passkey = 123456;

  TraceEvent((TwclBluetoothRadio*)Radio, "PasskeyRequest", "Address",
    IntToHex(Address, 12));
  TraceEvent(NULL, "", "Passkey", IntToStr((int)Passkey));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPinRequest(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address,
      String& Pin)
{
  Pin = edPin->Text;

  TraceEvent((TwclBluetoothRadio*)Radio, "PinRequest", "Address",
    IntToHex(Address, 12));
  TraceEvent(NULL, "", "PIN", Pin);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerStatusChanged(TObject *Sender,
      const TwclBluetoothRadio *Radio)
{
  String Status;
  if (((TwclBluetoothRadio*)Radio)->Available)
    Status = "Available";
  else
  {
    if (((TwclBluetoothRadio*)Radio)->Plugged)
      Status = "Not available, Plugged";
    else
      Status = "Unplugged";
  }
  TraceEvent((TwclBluetoothRadio*)Radio, "StatusChanged", "New status", Status);

  bool Found = false;
  for (int i = 0; i < lvRadios->Items->Count; i++)
  {
    if ((TwclBluetoothRadio*)lvRadios->Items->Item[i]->Data == (TwclBluetoothRadio*)Radio)
    {
      Found = true;
      RefreshRadio(lvRadios->Items->Item[i]);
      break;
    }
  }

  if (!Found)
  {
    TListItem* Item = lvRadios->Items->Add();
    Item->Data = (void*)Radio;

    Item->Caption = "";    // Api
    Item->SubItems->Add(""); // Available
    Item->SubItems->Add(""); // Address
    Item->SubItems->Add(""); // Connectable
    Item->SubItems->Add(""); // Discoverable
    Item->SubItems->Add(""); // HCI version
    Item->SubItems->Add(""); // LMP version
    Item->SubItems->Add(""); // Manufacturer
    Item->SubItems->Add(""); // Name
    Item->SubItems->Add(""); // COD

    RefreshRadio(Item);
  }

  if (cbDontTurnOff->Checked && ((TwclBluetoothRadio*)Radio)->Plugged && !((TwclBluetoothRadio*)Radio)->Available)
  {
    int Res = ((TwclBluetoothRadio*)Radio)->TurnOn();
    if (Res == WCL_E_BLUETOOTH_DRIVER_BUSY)
    {
      Sleep(200);
      Res = ((TwclBluetoothRadio*)Radio)->TurnOn();
    }
    if (Res != WCL_E_SUCCESS)
      TraceEvent((TwclBluetoothRadio*)Radio, "Turn ON", "Error", IntToHex(Res, 8));
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::ClearComPorts()
{
  lvVComs->Items->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btEnumVCOMsClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
    RefreshVComs();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::RefreshVComs()
{
  ClearComPorts();

  TListItem* Item = lvRadios->Selected;
  TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)(Item->Data);

  int Res;
  TwclVirtualComPorts Ports;
  if (cbEnumPreinstalled->Checked)
    Res = Radio->EnumComPorts(Ports);
  else
  {
    Ports = Radio->ComPorts;
    Res = WCL_E_SUCCESS;
  }

  if (Res != WCL_E_SUCCESS)
    ShowMessage("Error enumerating vCOMs: 0x" + IntToHex(Res, 8));

  else
  {
    for (int i = 0; i < Radio->ComPorts.Length; i++)
    {
      TwclVirtualComPort Port = Ports[i];

      Item = lvVComs->Items->Add();
      Item->Caption = Radio->ApiName;
      Item->SubItems->Add(IntToHex(Port.Address, 12));
      Item->SubItems->Add(Sysutils::GUIDToString(Port.Service));
      Item->SubItems->Add(IntToStr(Port.Number));

      Item->Data = Radio;
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btCreateVCOMClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
    if (lvServices->Selected == NULL)
      MessageDlg("Select service", mtWarning, TMsgDlgButtons() << mbOK, 0);
    else
    {
      TListItem* Item = lvDevices->Selected;
      TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)(Item->Data);
      __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);
      GUID Service = Sysutils::StringToGUID(lvServices->Selected->SubItems->Strings[2]);

      unsigned short Number;
      int Res = Radio->CreateComPort(Address, Service, Number);
      if (Res != WCL_E_SUCCESS)
        ShowError(Res);
      else
      {
        TraceEvent(Radio, "Create vCOM", "Number", IntToStr(Number));

        RefreshVComs();
      }
    }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btDestroyVCOMClick(TObject *Sender)
{
  if (lvVComs->Selected == NULL)
    MessageDlg("Select vCOM", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    TListItem* Item = lvVComs->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)(Item->Data);
    unsigned short Number = StrToInt(Item->SubItems->Strings[2]);

    int Res = Radio->DestroyComPort(Number);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
    else
    {
      TraceEvent(Radio, "Destroy vCOM", "Number", IntToStr(Number));

      RefreshVComs();
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btInstallDeviceClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    if (lvServices->Selected == NULL)
      MessageDlg("Select service", mtWarning, TMsgDlgButtons() << mbOK, 0);
    else
    {
      TListItem* Item = lvDevices->Selected;
      TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
      __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);
      #if __BORLANDC__ >= 0x0570
        GUID Service = Sysutils::StringToGUID(lvServices->Selected->SubItems->Strings[2]);
      #else
        GUID Service = StringToGUID(lvServices->Selected->SubItems->Strings[2]);
      #endif

      int Res = Radio->InstallDevice(Address, Service);
      if (Res == WCL_E_BLUETOOTH_DEVICE_ALREADY_INSTALLED)
      {
        // Reinstall to reconnect!
        Radio->UninstallDevice(Address, Service);
        Res = Radio->InstallDevice(Address, Service);
      }

      if (Res != WCL_E_SUCCESS)
        ShowError(Res);
      else
        MessageDlg("Device installed", mtInformation, TMsgDlgButtons() << mbOK, 0);
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btUninstallDeviceClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    if (lvServices->Selected == NULL)
      MessageDlg("Select service", mtWarning, TMsgDlgButtons() << mbOK, 0);
    else
    {
      TListItem* Item = lvDevices->Selected;
      TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
      __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);
      #if __BORLANDC__ >= 0x0570
      GUID Service = Sysutils::StringToGUID(lvServices->Selected->SubItems->Strings[2]);
      #else
      GUID Service = StringToGUID(lvServices->Selected->SubItems->Strings[2]);
      #endif

      int Res = Radio->UninstallDevice(Address, Service);
      if (Res != WCL_E_SUCCESS)
        ShowError(Res);
      else
        MessageDlg("Device uninstalled", mtInformation, TMsgDlgButtons() << mbOK, 0);
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btIsInRangeClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    bool InRange = false;
    int Res = Radio->IsRemoteDeviceInRange(Address, InRange);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
    else
    {
      if (InRange)
        ShowMessage("Device is in range");
      else
        ShowMessage("Device is NOT in range");
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBluetoothManagerConfirm(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address, bool& Confirm)
{
  Confirm = true;

  TraceEvent((TwclBluetoothRadio*)Radio, "Just Works pairing", "Address",
    IntToHex(Address, 12));
}
//---------------------------------------------------------------------------


void __fastcall TfmMain::wclBluetoothManagerIoCapabilityRequest(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, TwclBluetoothMitmProtection& Mitm,
      TwclBluetoothIoCapability& IoCapability, bool& OobPresent)
{
  switch (cbMitmProtection->ItemIndex)
  {
    case 0:
      Mitm = mitmProtectionNotRequired;
      break;
    case 1:
      Mitm = mitmProtectionRequired;
      break;
    case 2:
      Mitm = mitmProtectionNotRequiredBonding;
      break;
    case 3:
      Mitm = mitmProtectionRequiredBonding;
      break;
    case 4:
      Mitm = mitmProtectionNotRequiredGeneralBonding;
      break;
    case 5:
      Mitm = mitmProtectionRequiredGeneralBonding;
      break;
    default:
      Mitm = mitmProtectionNotDefined;
      break;
  }

  switch (cbIoCap->ItemIndex)
  {
    case 0:
      IoCapability = iocapDisplayOnly;
      break;
    case 1:
      IoCapability = iocapDisplayYesNo;
      break;
    case 2:
      IoCapability = iocapKeyboardOnly;
      break;
    case 3:
      IoCapability = iocapNoInputNoOutput;
      break;
    case 4:
      IoCapability = iocapDisplayKeyboard;
      break;
    default:
      IoCapability = iocapNotDefined;
      break;
  }

  // To accept OOB pairing set this parameter to True.
  OobPresent = false;
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBluetoothManagerOobDataRequest(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address,
      TwclBluetoothOobData &OobData)
{
  // This event fires when a remote device requests OOB data.
  ZeroMemory(&OobData, sizeof(TwclBluetoothOobData));
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBluetoothManagerProtectionLevelRequest(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, TwclBluetoothLeProtectionLevel& Protection)
{
  switch (cbBleProtection->ItemIndex)
  {
    case 0:
      Protection = pplDefault;
      break;
    case 1:
      Protection = pplNone;
      break;
    case 2:
      Protection = pplEncryption;
      break;
    case 3:
      Protection = pplEncryptionAndAuthentication;
      break;
    default:
      Protection = pplDefault;
      break;
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::FormCreate(TObject *Sender)
{
  FPowerMonitor = new TwclPowerEventsMonitor();
  FPowerMonitor->OnPowerStateChanged = PowerStateChanged;
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::PowerStateChanged(TObject* Sender,
  const TwclPowerState State)
{
  static bool WasOpened = false;

  switch (State)
  {
    case psResumeAutomatic:
      TraceEvent(NULL, "Power", "State", "psResumeAutomatic");
      if (WasOpened)
      {
        WasOpened = false;
        wclBluetoothManager->Open();
      }
      break;

    case psResume:
      TraceEvent(NULL, "Power", "State", "psResume");
      break;

    case psSuspend:
      TraceEvent(NULL, "Power", "State", "psSuspend");
      if (wclBluetoothManager->Active)
      {
          WasOpened = true;
          wclBluetoothManager->Close();
      }
	  break;

	case psPowerStatusChanged:
	  TraceEvent(NULL, "Power", "State", "psPowerStatusChanged");
	  break;

	case psUnknown:
	  TraceEvent(NULL, "Power", "State", "psUnknown");
	  break;
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerClosed(TObject *Sender)
{
  ClearRadios();        
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::ntDisconnectClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);
    int Res = Radio->RemoteDisconnect(Address);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btEnumConnectedClick(TObject *Sender)
{
  if (lvRadios->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    ClearDevices();

    TListItem* Item = lvRadios->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;

    TwclBluetoothAddresses Devices;
    int Res = Radio->EnumConnectedDevices(Devices);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    else
    {
      for (int i = 0; i < Devices.Length; i++)
        AddDevice(Radio, Devices[i]);

      RefreshDevices();
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btEnumInstalledServicesClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select radio", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    ClearServices();

    TListItem* Item = lvDevices->Selected;
    TwclBluetoothRadio* Radio = (TwclBluetoothRadio*)Item->Data;
    __int64 Address = StrToInt64("$" + Item->SubItems->Strings[0]);

    TwclBluetoothInstalledServices Services;
    int Res = Radio->EnumInstalledServices(Address, Services);
    if (Res != WCL_E_SUCCESS)
      ShowError(Res);

    else
    {
      if (Services.Length > 0)
      {
        for (int i = 0; i < Services.Length; i++)
        {
          Item = lvServices->Items->Add();

          Item->Caption = Radio->ApiName;
          Item->SubItems->Add(IntToHex(Address, 12));
          Item->SubItems->Add("");
          Item->SubItems->Add(Sysutils::GUIDToString(Services[i]));
          Item->SubItems->Add("");
          Item->SubItems->Add("");
          Item->SubItems->Add("");
        }
      }
    }
  }
}
//---------------------------------------------------------------------------

