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

#include <vcl.h>
#pragma hdrstop

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

#ifdef _WIN64
#pragma comment(lib, "wclCommon.a")
#pragma comment(lib, "wclCommunication.a")
#pragma comment(lib, "wclBluetoothFrameworkR.a")
#else
#pragma comment(lib, "wclCommon.lib")
#pragma comment(lib, "wclCommunication.lib")
#pragma comment(lib, "wclBluetoothFrameworkR.lib")
#endif

TfmMain *fmMain;
//---------------------------------------------------------------------------
__fastcall TfmMain::TfmMain(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btClearClick(TObject *Sender)
{
  lbPackets->Items->Clear();       
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btStartClick(TObject *Sender)
{
  int Res = wclBleSniffer->Start(cbChannel->ItemIndex + 37);
  if (Res != WCL_E_SUCCESS)
    ShowMessage("Start failed: 0x" + IntToHex(Res, 8));
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btStopClick(TObject *Sender)
{
  int Res = wclBleSniffer->Stop();
  if (Res != WCL_E_SUCCESS)
    ShowMessage("Stop failed: 0x" + IntToHex(Res, 8));
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferStarted(TObject *Sender)
{
  lbPackets->Items->Add("Started");        
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferStopped(TObject *Sender)
{
  lbPackets->Items->Add("Stopped");        
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::FormDestroy(TObject *Sender)
{
  wclBleSniffer->Stop();        
}
//---------------------------------------------------------------------------


void __fastcall TfmMain::wclBleSnifferRawPacketReceived(TObject *Sender,
      const TwclBluetoothLePacketHeader &Header, const Pointer Payload,
      const WORD Size)
{
  lbPackets->Items->Add("RAW PACKET RECEIVED");
  DumpHeader(Header);
  DumpPayload(Payload, Size);
}
//---------------------------------------------------------------------------


void TfmMain::DumpHeader(const TwclBluetoothLePacketHeader& Header)
{
  lbPackets->Items->Add("   HEADER");
  lbPackets->Items->Add("  ========");
  lbPackets->Items->Add("    Timestamp: " + IntToHex((int)Header.Timestamp, 8));
  lbPackets->Items->Add("    Access Address: " +
    IntToHex((int)Header.AccessAddress, 8));
  lbPackets->Items->Add("    Channel: " + IntToHex(Header.Channel, 2));
  lbPackets->Items->Add("    Crc: " + IntToHex((int)Header.Crc, 8));
  lbPackets->Items->Add("    Rssi: " + IntToStr(Header.Rssi));
  if (Header.Valid)
    lbPackets->Items->Add("    PACKET: OK");
  else
    lbPackets->Items->Add("    PACKET: ERROR");
}
//---------------------------------------------------------------------------

void TfmMain::DumpPayload(const Pointer Payload, const WORD Size)
{
  if (Payload != NULL && Size > 0)
  {
    lbPackets->Items->Add("   PAYLOAD");
    lbPackets->Items->Add("  =========");

    String Str = "";
    WORD Ndx = 1;
    for (WORD i = 0; i < Size; i++)
    {
      Str = Str + IntToHex(((unsigned char*)Payload)[i], 2) + " ";
      Ndx++;
      if (Ndx == 16)
      {
        lbPackets->Items->Add("    " + Str);
        Str = "";
        Ndx = 1;
      }
    }
    if (Str != "")
      lbPackets->Items->Add("    " + Str);
  }
  lbPackets->Items->Add("");
}
//---------------------------------------------------------------------------

void TfmMain::DumpPduHeader(
  const TwclBluetoothLeAdvertisingPduHeader& PduHeader)
{
  DumpHeader(PduHeader.Header);
  lbPackets->Items->Add("   PDU HEADER");
  lbPackets->Items->Add("  ============");
  lbPackets->Items->Add("    ChSel: " + BoolToStr(PduHeader.ChSel, true));
  lbPackets->Items->Add("    TxAdd: " + BoolToStr(PduHeader.TxAdd, true));
  lbPackets->Items->Add("    RxAdd: " + BoolToStr(PduHeader.RxAdd, true));
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferAdvDirectIndReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 AdvA, const __int64 TargetA)
{
  lbPackets->Items->Add("ADV_DIRECT_IND RECEIVED");
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  lbPackets->Items->Add("  TargetA: " + IntToHex(TargetA, 12));
  DumpPduHeader(PduHeader);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferAdvIndReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 AdvA, const Pointer AdvData, const BYTE AdvDataLen)
{
  lbPackets->Items->Add("ADV_IND RECEIVED");
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  DumpPduHeader(PduHeader);
  DumpPayload(AdvData, AdvDataLen);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferAdvNonConnIndReceived(
      TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 AdvA, const Pointer AdvData, const BYTE AdvDataLen)
{
  lbPackets->Items->Add("ADV_NONCONN_IND RECEIVED");
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  DumpPduHeader(PduHeader);
  DumpPayload(AdvData, AdvDataLen);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferAdvScanIndReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 AdvA, const Pointer AdvData, const BYTE AdvDataLen)
{
  lbPackets->Items->Add("ADV_SCAN_IND RECEIVED");
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  DumpPduHeader(PduHeader);
  DumpPayload(AdvData, AdvDataLen);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferScanReqReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 ScanA, const __int64 AdvA)
{
  lbPackets->Items->Add("SCAN_REQ RECEIVED");
  lbPackets->Items->Add("  ScanA: " + IntToHex(ScanA, 12));
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  DumpPduHeader(PduHeader);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferScanRspReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 AdvA, const Pointer ScanRspData,
      const BYTE ScanRspDataLen)
{
  lbPackets->Items->Add("SCAN_RSP RECEIVED");
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  DumpPduHeader(PduHeader);
  DumpPayload(ScanRspData, ScanRspDataLen);
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBleSnifferConnectIndReceived(TObject *Sender,
      const TwclBluetoothLeAdvertisingPduHeader &PduHeader,
      const __int64 InitA, const __int64 AdvA,
      const TwclBleSnifferLlData &LlData)
{
  lbPackets->Items->Add("CONNECT_IND RECEIVED");
  lbPackets->Items->Add("  InitA: " + IntToHex(InitA, 12));
  lbPackets->Items->Add("  AdvA: " + IntToHex(AdvA, 12));
  lbPackets->Items->Add("  LLDATA");
  lbPackets->Items->Add("    Aa: " + IntToHex((int)LlData.Aa, 8));
  lbPackets->Items->Add("    CrcInit: " + IntToHex((int)LlData.CrcInit, 8));
  lbPackets->Items->Add("    WinSize: " + IntToStr(LlData.WinSize));
  lbPackets->Items->Add("    WinOffset: " + IntToStr(LlData.WinOffset));
  lbPackets->Items->Add("    Interval: " + IntToStr(LlData.Interval));
  lbPackets->Items->Add("    Latency: " + IntToStr(LlData.Latency));
  lbPackets->Items->Add("    Timeout: " + IntToStr(LlData.Timeout));
  lbPackets->Items->Add("    ChM: " + IntToHex(LlData.ChM, 16));
  lbPackets->Items->Add("    Hop: " + IntToStr(LlData.Hop));
  lbPackets->Items->Add("    Sca: " + IntToStr(LlData.Sca));
  DumpPduHeader(PduHeader);
}
//---------------------------------------------------------------------------

