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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "nrclasses"
#pragma link "nrcommbox"
#pragma link "nrhid"
#pragma link "CSPIN"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::nrHid1Close(TObject *Sender)
{
  CheckBox1->Checked = false;        
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AddInfo(AnsiString sCapt, AnsiString sVal)
{
        TListItem *Itm;
        if(sVal.Trim() == "") return;
        Itm = ListView1->Items->Add();
        Itm->Caption = sCapt;
        Itm->SubItems->Add(sVal);
}
void __fastcall TForm1::nrHid1AfterReceive(TObject *Com, Pointer Buffer,
      DWORD Received)
{
        AnsiString s = "HID Report is received: " + IntToStr(Received) + " bytes ";
        for(int i = 0; i < (int)Received; i++)
                s += IntToHex(Byte(PChar(Buffer)[i]),2) + " ";
        Memo1->Lines->Add(s);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
        try
        {
                nrHid1->Active = CheckBox1->Checked;
        }
        catch(...)
        {
                CheckBox1->Checked = nrHid1->Active;
                throw;
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateTreeInfo()
{
        TTreeNode *itm;
        TreeView1->Items->Clear();

        if(nrHid1->HidDevice != NULL){

                itm = TreeView1->Items->Add(NULL,"General HID Info");

                if(nrHid1->HidDevice->InputButtonsCount > 0)
                {
                        itm = TreeView1->Items->Add(itm,"Input Buttons");
                        for(int i = 0; i < nrHid1->HidDevice->InputButtonsCount; i++)
                                TreeView1->Items->AddChild(itm,"Input Button " + IntToStr(i));
                 }
                if(nrHid1->HidDevice->InputValuesCount > 0){
                        itm = TreeView1->Items->Add(itm,"Input Values");
                        itm->Data = Pointer(1);
                        for(int i = 0; i < nrHid1->HidDevice->InputValuesCount; i++)
                                TreeView1->Items->AddChild(itm,"Input Values " + IntToStr(i));
                }

                if(nrHid1->HidDevice->OutputButtonsCount > 0){
                        itm = TreeView1->Items->Add(itm,"Output Buttons");
                        itm->Data = Pointer(2);
                        for(int i = 0; i < nrHid1->HidDevice->OutputButtonsCount; i++)
                                TreeView1->Items->AddChild(itm,"Output Button " + IntToStr(i));
                }

                if(nrHid1->HidDevice->OutputValuesCount > 0){
                        itm = TreeView1->Items->Add(itm,"Output Values");
                        itm->Data = Pointer(3);
                        for(int i = 0; i < nrHid1->HidDevice->OutputValuesCount; i++)
                                TreeView1->Items->AddChild(itm,"Output Values " + IntToStr(i));
                }

                if(nrHid1->HidDevice->FeatureButtonsCount > 0){
                        itm = TreeView1->Items->Add(itm,"Feature Buttons");
                        itm->Data = Pointer(4);
                        for(int i = 0; i < nrHid1->HidDevice->FeatureButtonsCount; i++)
                                TreeView1->Items->AddChild(itm,"Feature Button " + IntToStr(i));
                }

                if(nrHid1->HidDevice->FeatureValuesCount > 0){
                        itm = TreeView1->Items->Add(itm,"Feature Values");
                        itm->Data = Pointer(5);
                        for(int i = 0; i < nrHid1->HidDevice->FeatureValuesCount; i++)
                                TreeView1->Items->AddChild(itm, "Feature Values " + IntToStr(i));
                }
        }

        if (TreeView1->Items->Count > 0) TreeView1->Selected = TreeView1->Items->Item[0];

        UpdateListViewInfo();

}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateListViewInfo()
{
        HIDP_BUTTON_CAPS *btns;
        HIDP_VALUE_CAPS vals;
        AnsiString s = "";

        ListView1->Clear();
        if ((TreeView1->Selected != NULL) && (nrHid1->HidDevice != NULL)){

        if(TreeView1->Selected->AbsoluteIndex == 0) UpdateGeneralInfo();

        if(TreeView1->Selected->Level > 0){

                //nrHid1->HidDevice->InputButtons->Items[TreeView1->Selected->Index]
                switch((int)TreeView1->Selected->Parent->Data)
                {
                        case 0: btns = &(nrHid1->HidDevice->InputButtons[TreeView1->Selected->Index]);
                                OutputDebugStringA("aaa");
                                break;
                        case 1:

                                //nrHid1->HidDevice->InputButtons.
                                vals = nrHid1->HidDevice->InputValues[TreeView1->Selected->Index];
                                s = IntToStr(nrHid1->HidDevice->InputValues[TreeView1->Selected->Index].UsagePage);
                                OutputDebugStringA((char*)s.data());
                                s = IntToStr(TreeView1->Selected->Index);
                                OutputDebugStringA((char*)s.data());
                                break;
                        case 2: btns = &(nrHid1->HidDevice->OutputButtons[TreeView1->Selected->Index]); break;
                        case 3: vals = nrHid1->HidDevice->OutputValues[TreeView1->Selected->Index]; break;
                        case 4: btns = &(nrHid1->HidDevice->FeatureButtons[TreeView1->Selected->Index]); break;
                        case 5: vals = nrHid1->HidDevice->FeatureValues[TreeView1->Selected->Index]; break;
                }

                if ((((int)TreeView1->Selected->Parent->Data) & 1) == 0)
                        UpdateButtonsInfo(btns);
                else
                        UpdateValuesInfo(vals);
    }
  }

}

//---------------------------------------------------------------------------
void __fastcall TForm1::nrDeviceBox1Change(TObject *Sender)
{
        UpdateTreeInfo();
}

void __fastcall TForm1::UpdateGeneralInfo()
{
        AddInfo("Friendly Name", nrHid1->HidDevice->NameFriendly);
        AddInfo("Description", nrHid1->HidDevice->Description);
        AddInfo("Manufacturer", nrHid1->HidDevice->Manufacturer);
        AddInfo("Service", nrHid1->HidDevice->Service);
        AddInfo("VendorID", IntToHex(nrHid1->HidDevice->VendorId, 4));
        AddInfo("ProductID", IntToHex(nrHid1->HidDevice->ProductId, 4));
        AddInfo("Ver", IntToStr(nrHid1->HidDevice->Version) + " [" + IntToHex(nrHid1->HidDevice->Version, 4) + "h]");
        AddInfo("Usage Page", IntToHex(nrHid1->HidDevice->UsagePage, 4) + " (" + GetUsagePageString(nrHid1->HidDevice->UsagePage) + ")");

        if( nrHid1->Active)
                AddInfo("R/W modes:", BoolToStr(nrHid1->IsReadMode,true) + " / " + BoolToStr(nrHid1->IsWriteMode,true));
}

void __fastcall TForm1::UpdateButtonsInfo(HIDP_BUTTON_CAPS *v)
{
        AddInfo("Usage Page", IntToHex(v->UsagePage, 4) + " (" + GetUsagePageString(v->UsagePage) + ")");
        AddInfo("Report ID", IntToHex(v->ReportID, 2));
        AddInfo("Bit Field", IntToHex(v->BitField, 4));
        AddInfo("Is Range", BoolToStr(v->IsRange, true));
        AddInfo("Is Designator Range", BoolToStr(v->IsDesignatorRange, true));
        if(v->IsRange){
                AddInfo("Usage Min/Max", IntToStr(v->Range.UsageMin) + " / " + IntToStr(v->Range.UsageMax));
                AddInfo("String Min/Max", IntToStr(v->Range.StringMin) + " / " + IntToStr(v->Range.StringMax));
                AddInfo("Designator Min/Max", IntToStr(v->Range.DesignatorMin) + " / " + IntToStr(v->Range.DesignatorMax));
                AddInfo("Data Index Min/Max", IntToStr(v->Range.DataIndexMin) + " / " + IntToStr(v->Range.DataIndexMax));
        } else {
                AddInfo("Usage", IntToStr(v->NotRange.Usage) + " [" + IntToHex(v->NotRange.Usage,4) + "h]");
                AddInfo("String", IntToStr(v->NotRange.StringIndex));
                AddInfo("Designator", IntToStr(v->NotRange.DesignatorIndex));
                AddInfo("Data Index", IntToStr(v->NotRange.DataIndex));
        }
}

void __fastcall TForm1::UpdateValuesInfo(HIDP_VALUE_CAPS v)
{
        AddInfo("Usage Page", IntToHex(v.UsagePage, 4)  + " (" + GetUsagePageString(v.UsagePage) + ")" );
        AddInfo("Report ID", IntToHex(v.ReportID, 2));
        AddInfo("Bit Field", IntToHex(v.BitField, 4));
        AddInfo("Is Range", BoolToStr(v.IsRange, True));
        AddInfo("Is Designator Range", BoolToStr(v.IsDesignatorRange, True));
        if(v.IsRange){
                AddInfo("Usage Min/Max", IntToStr(v.Range.UsageMin) + " / " + IntToStr(v.Range.UsageMax));
                AddInfo("String Min/Max", IntToStr(v.Range.StringMin) + " / " + IntToStr(v.Range.StringMax));
                AddInfo("Designator Min/Max", IntToStr(v.Range.DesignatorMin) + " / " + IntToStr(v.Range.DesignatorMax));
                AddInfo("Data Index Min/Max", IntToStr(v.Range.DataIndexMin) + " / " + IntToStr(v.Range.DataIndexMax));
        } else {
                AddInfo("Usage", IntToStr(v.NotRange.Usage) + " [" + IntToHex(v.NotRange.Usage,4) + "h]");
                AddInfo("String", IntToStr(v.NotRange.StringIndex));
                AddInfo("Designator", IntToStr(v.NotRange.DesignatorIndex));
                AddInfo("Data Index", IntToStr(v.NotRange.DataIndex));
        }
}

//---------------------------------------------------------------------------
void __fastcall TForm1::TreeView1Change(TObject *Sender, TTreeNode *Node)
{
        UpdateListViewInfo();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::bSendClick(TObject *Sender)
{
        AnsiString s;

        // prepare data string and place Report ID into first byte
        s = (AnsiString) ((char) eID->Value) + Edit1->Text;

        // send HID report
        nrHid1->SendString(s);

        // also the following methods are possible too:
        //nrHid1->WriteReport(s.c_str(), s.Length());
        //nrHid1->SetOutputReport(s.c_str(), s.Length());
}
//---------------------------------------------------------------------------

