{*******************************************************}
{                                                       }
{       nrCommLib Communication Library for Delphi      }
{       HID API routines for Win32                      }
{       Copyright (c) 1997-2011 Roman Novgorodov        }
{       v9.27                                           }
{       last update: 20 Apr 2008                        }
{                                                       }
{       e-mail:noro@deepsoftware.com                    }
{       DeepSoftware                                    }
{       http://www.deepsoftware.com/                    }
{                                                       }
{*******************************************************}
{$I nrcommlib.inc}
unit nrhidw32;
interface
uses windows;

Const

  // return status codes ...
  FACILITY_HID_ERROR_CODE              = $11;
  HIDP_STATUS_SUCCESS                  = (0 shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 0;
  HIDP_STATUS_NULL                     = ($8 shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 1;
  HIDP_STATUS_INVALID_PREPARSED_DATA   = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 1;
  HIDP_STATUS_INVALID_REPORT_TYPE      = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 2;
  HIDP_STATUS_INVALID_REPORT_LENGTH    = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 3;
  HIDP_STATUS_USAGE_NOT_FOUND          = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 4;
  HIDP_STATUS_VALUE_OUT_OF_RANGE       = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 5;
  HIDP_STATUS_BAD_LOG_PHY_VALUES       = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 6;
  HIDP_STATUS_BUFFER_TOO_SMALL         = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 7;
  HIDP_STATUS_INTERNAL_ERROR           = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 8;
  HIDP_STATUS_I8042_TRANS_UNKNOWN      = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or 9;
  HIDP_STATUS_INCOMPATIBLE_REPORT_ID   = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $a;
  HIDP_STATUS_NOT_VALUE_ARRAY          = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $b;
  HIDP_STATUS_IS_VALUE_ARRAY           = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $c;
  HIDP_STATUS_DATA_INDEX_NOT_FOUND     = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $d;
  HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE  = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $e;
  HIDP_STATUS_BUTTON_NOT_PRESSED       = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $f;
  HIDP_STATUS_REPORT_DOES_NOT_EXIST    = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $10;
  HIDP_STATUS_NOT_IMPLEMENTED          = ($c shl 28) or (FACILITY_HID_ERROR_CODE shl 16) or $20;
  HIDP_STATUS_I8242_TRANS_UNKNOWN      = HIDP_STATUS_I8042_TRANS_UNKNOWN;

  // Usage Pages
  HID_USAGE_PAGE_UNDEFINED                  = $00;
  HID_USAGE_PAGE_GENERIC                    = $01;
  HID_USAGE_PAGE_SIMULATION                 = $02;
  HID_USAGE_PAGE_VR                         = $03;
  HID_USAGE_PAGE_SPORT                      = $04;
  HID_USAGE_PAGE_GAME                       = $05;
  HID_USAGE_PAGE_KEYBOARD                   = $07;
  HID_USAGE_PAGE_LED                        = $08;
  HID_USAGE_PAGE_BUTTON                     = $09;
  HID_USAGE_PAGE_ORDINAL                    = $0A;
  HID_USAGE_PAGE_TELEPHONY                  = $0B;
  HID_USAGE_PAGE_CONSUMER                   = $0C;
  HID_USAGE_PAGE_DIGITIZER                  = $0D;
  HID_USAGE_PAGE_UNICODE                    = $10;
  HID_USAGE_PAGE_ALPHANUMERIC               = $14;

  // Usages from Generic Desktop Page (0x01)
  HID_USAGE_GENERIC_POINTER                  = $01;
  HID_USAGE_GENERIC_MOUSE                    = $02;
  HID_USAGE_GENERIC_JOYSTICK                 = $04;
  HID_USAGE_GENERIC_GAMEPAD                  = $05;
  HID_USAGE_GENERIC_KEYBOARD                 = $06;
  HID_USAGE_GENERIC_KEYPAD                   = $07;
  HID_USAGE_GENERIC_SYSTEM_CTL               = $80;

  HID_USAGE_GENERIC_X                        = $30;
  HID_USAGE_GENERIC_Y                        = $31;
  HID_USAGE_GENERIC_Z                        = $32;
  HID_USAGE_GENERIC_RX                       = $33;
  HID_USAGE_GENERIC_RY                       = $34;
  HID_USAGE_GENERIC_RZ                       = $35;
  HID_USAGE_GENERIC_SLIDER                   = $36;
  HID_USAGE_GENERIC_DIAL                     = $37;
  HID_USAGE_GENERIC_WHEEL                    = $38;
  HID_USAGE_GENERIC_HATSWITCH                = $39;
  HID_USAGE_GENERIC_COUNTED_BUFFER           = $3A;
  HID_USAGE_GENERIC_BYTE_COUNT               = $3B;
  HID_USAGE_GENERIC_MOTION_WAKEUP            = $3C;
  HID_USAGE_GENERIC_VX                       = $40;
  HID_USAGE_GENERIC_VY                       = $41;
  HID_USAGE_GENERIC_VZ                       = $42;
  HID_USAGE_GENERIC_VBRX                     = $43;
  HID_USAGE_GENERIC_VBRY                     = $44;
  HID_USAGE_GENERIC_VBRZ                     = $45;
  HID_USAGE_GENERIC_VNO                      = $46;
  HID_USAGE_GENERIC_SYSCTL_POWER             = $81;
  HID_USAGE_GENERIC_SYSCTL_SLEEP             = $82;
  HID_USAGE_GENERIC_SYSCTL_WAKE              = $83;
  HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU      = $84;
  HID_USAGE_GENERIC_SYSCTL_MAIN_MENU         = $85;
  HID_USAGE_GENERIC_SYSCTL_APP_MENU          = $86;
  HID_USAGE_GENERIC_SYSCTL_HELP_MENU         = $87;
  HID_USAGE_GENERIC_SYSCTL_MENU_EXIT         = $88;
  HID_USAGE_GENERIC_SYSCTL_MENU_SELECT       = $89;
  HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT        = $8A;
  HID_USAGE_GENERIC_SYSCTL_MENU_LEFT         = $8B;
  HID_USAGE_GENERIC_SYSCTL_MENU_UP           = $8C;
  HID_USAGE_GENERIC_SYSCTL_MENU_DOWN         = $8D;

  // Usages from Simulation Controls Page (0x02)
  HID_USAGE_SIMULATION_RUDDER                = $BA;
  HID_USAGE_SIMULATION_THROTTLE              = $BB;

  // Keyboard/Keypad Page (0x07)
  // Error "keys"
  HID_USAGE_KEYBOARD_NOEVENT                 = $00;
  HID_USAGE_KEYBOARD_ROLLOVER                = $01;
  HID_USAGE_KEYBOARD_POSTFAIL                = $02;
  HID_USAGE_KEYBOARD_UNDEFINED               = $03;

  // Letters
  HID_USAGE_KEYBOARD_aA                      = $04;
  HID_USAGE_KEYBOARD_zZ                      = $1D;
  // Numbers
  HID_USAGE_KEYBOARD_ONE                     = $1E;
  HID_USAGE_KEYBOARD_ZERO                    = $27;
  // Modifier Keys
  HID_USAGE_KEYBOARD_LCTRL                   = $E0;
  HID_USAGE_KEYBOARD_LSHFT                   = $E1;
  HID_USAGE_KEYBOARD_LALT                    = $E2;
  HID_USAGE_KEYBOARD_LGUI                    = $E3;
  HID_USAGE_KEYBOARD_RCTRL                   = $E4;
  HID_USAGE_KEYBOARD_RSHFT                   = $E5;
  HID_USAGE_KEYBOARD_RALT                    = $E6;
  HID_USAGE_KEYBOARD_RGUI                    = $E7;
  HID_USAGE_KEYBOARD_SCROLL_LOCK             = $47;
  HID_USAGE_KEYBOARD_NUM_LOCK                = $53;
  HID_USAGE_KEYBOARD_CAPS_LOCK               = $39;
  // Funtion keys
  HID_USAGE_KEYBOARD_F1                      = $3A;
  HID_USAGE_KEYBOARD_F12                     = $45;

  HID_USAGE_KEYBOARD_RETURN                  = $28;
  HID_USAGE_KEYBOARD_ESCAPE                  = $29;
  HID_USAGE_KEYBOARD_DELETE                  = $2A;

  HID_USAGE_KEYBOARD_PRINT_SCREEN            = $46;

  // LED Page (0x08)
  HID_USAGE_LED_NUM_LOCK                     = $01;
  HID_USAGE_LED_CAPS_LOCK                    = $02;
  HID_USAGE_LED_SCROLL_LOCK                  = $03;
  HID_USAGE_LED_COMPOSE                      = $04;
  HID_USAGE_LED_KANA                         = $05;
  HID_USAGE_LED_POWER                        = $06;
  HID_USAGE_LED_SHIFT                        = $07;
  HID_USAGE_LED_DO_NOT_DISTURB               = $08;
  HID_USAGE_LED_MUTE                         = $09;
  HID_USAGE_LED_TONE_ENABLE                  = $0A;
  HID_USAGE_LED_HIGH_CUT_FILTER              = $0B;
  HID_USAGE_LED_LOW_CUT_FILTER               = $0C;
  HID_USAGE_LED_EQUALIZER_ENABLE             = $0D;
  HID_USAGE_LED_SOUND_FIELD_ON               = $0E;
  HID_USAGE_LED_SURROUND_FIELD_ON            = $0F;
  HID_USAGE_LED_REPEAT                       = $10;
  HID_USAGE_LED_STEREO                       = $11;
  HID_USAGE_LED_SAMPLING_RATE_DETECT         = $12;
  HID_USAGE_LED_SPINNING                     = $13;
  HID_USAGE_LED_CAV                          = $14;
  HID_USAGE_LED_CLV                          = $15;
  HID_USAGE_LED_RECORDING_FORMAT_DET         = $16;
  HID_USAGE_LED_OFF_HOOK                     = $17;
  HID_USAGE_LED_RING                         = $18;
  HID_USAGE_LED_MESSAGE_WAITING              = $19;
  HID_USAGE_LED_DATA_MODE                    = $1A;
  HID_USAGE_LED_BATTERY_OPERATION            = $1B;
  HID_USAGE_LED_BATTERY_OK                   = $1C;
  HID_USAGE_LED_BATTERY_LOW                  = $1D;
  HID_USAGE_LED_SPEAKER                      = $1E;
  HID_USAGE_LED_HEAD_SET                     = $1F;
  HID_USAGE_LED_HOLD                         = $20;
  HID_USAGE_LED_MICROPHONE                   = $21;
  HID_USAGE_LED_COVERAGE                     = $22;
  HID_USAGE_LED_NIGHT_MODE                   = $23;
  HID_USAGE_LED_SEND_CALLS                   = $24;
  HID_USAGE_LED_CALL_PICKUP                  = $25;
  HID_USAGE_LED_CONFERENCE                   = $26;
  HID_USAGE_LED_STAND_BY                     = $27;
  HID_USAGE_LED_CAMERA_ON                    = $28;
  HID_USAGE_LED_CAMERA_OFF                   = $29;
  HID_USAGE_LED_ON_LINE                      = $2A;
  HID_USAGE_LED_OFF_LINE                     = $2B;
  HID_USAGE_LED_BUSY                         = $2C;
  HID_USAGE_LED_READY                        = $2D;
  HID_USAGE_LED_PAPER_OUT                    = $2E;
  HID_USAGE_LED_PAPER_JAM                    = $2F;
  HID_USAGE_LED_REMOTE                       = $30;
  HID_USAGE_LED_FORWARD                      = $31;
  HID_USAGE_LED_REVERSE                      = $32;
  HID_USAGE_LED_STOP                         = $33;
  HID_USAGE_LED_REWIND                       = $34;
  HID_USAGE_LED_FAST_FORWARD                 = $35;
  HID_USAGE_LED_PLAY                         = $36;
  HID_USAGE_LED_PAUSE                        = $37;
  HID_USAGE_LED_RECORD                       = $38;
  HID_USAGE_LED_ERROR                        = $39;
  HID_USAGE_LED_SELECTED_INDICATOR           = $3A;
  HID_USAGE_LED_IN_USE_INDICATOR             = $3B;
  HID_USAGE_LED_MULTI_MODE_INDICATOR         = $3C;
  HID_USAGE_LED_INDICATOR_ON                 = $3D;
  HID_USAGE_LED_INDICATOR_FLASH              = $3E;
  HID_USAGE_LED_INDICATOR_SLOW_BLINK         = $3F;
  HID_USAGE_LED_INDICATOR_FAST_BLINK         = $40;
  HID_USAGE_LED_INDICATOR_OFF                = $41;
  HID_USAGE_LED_FLASH_ON_TIME                = $42;
  HID_USAGE_LED_SLOW_BLINK_ON_TIME           = $43;
  HID_USAGE_LED_SLOW_BLINK_OFF_TIME          = $44;
  HID_USAGE_LED_FAST_BLINK_ON_TIME           = $45;
  HID_USAGE_LED_FAST_BLINK_OFF_TIME          = $46;
  HID_USAGE_LED_INDICATOR_COLOR              = $47;
  HID_USAGE_LED_RED                          = $48;
  HID_USAGE_LED_GREEN                        = $49;
  HID_USAGE_LED_AMBER                        = $4A;
  HID_USAGE_LED_GENERIC_INDICATOR            = $4B;

  //  Telephony Device Page (0x0B)
  HID_USAGE_TELEPHONY_PHONE                  = $01;
  HID_USAGE_TELEPHONY_ANSWERING_MACHINE      = $02;
  HID_USAGE_TELEPHONY_MESSAGE_CONTROLS       = $03;
  HID_USAGE_TELEPHONY_HANDSET                = $04;
  HID_USAGE_TELEPHONY_HEADSET                = $05;
  HID_USAGE_TELEPHONY_KEYPAD                 = $06;
  HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON    = $07;

  // and others...
  HID_USAGE_CONSUMERCTRL                     = $01;
  HID_USAGE_DIGITIZER_PEN                    = $02;
  HID_USAGE_DIGITIZER_IN_RANGE               = $32;
  HID_USAGE_DIGITIZER_TIP_SWITCH             = $42;
  HID_USAGE_DIGITIZER_BARREL_SWITCH          = $44;

Type

  HIDD_ATTRIBUTES = packed record
    Size : DWORD;
    VendorID:WORD;
    ProductID:WORD;
    VersionNumber:WORD;
  end;
  PHIDD_ATTRIBUTES = ^HIDD_ATTRIBUTES;

  HIDP_CAPS  = packed record
    Usage:WORD;
    UsagePage:WORD;
    InputReportByteLength:WORD;
    OutputReportByteLength:WORD;
    FeatureReportByteLength:WORD;
    Reserved:array [0..16] of WORD;
    NumberLinkCollectionNodes:WORD;
    NumberInputButtonCaps:WORD;
    NumberInputValueCaps:WORD;
    NumberInputDataIndices:WORD;
    NumberOutputButtonCaps:WORD;
    NumberOutputValueCaps:WORD;
    NumberOutputDataIndices:WORD;
    NumberFeatureButtonCaps:WORD;
    NumberFeatureValueCaps:WORD;
    NumberFeatureDataIndices:WORD;
  end;

  HIDP_REPORT_TYPE = ( HidP_Input, HidP_Output, HidP_Feature);

  HIDP_BUTTON_CAPS = packed record
    UsagePage : word;
    ReportID : byte;
    IsAlias:BOOLEAN;
    BitField : word;
    LinkCollection : word;   // A unique internal index pointer
    LinkUsage:word;
    LinkUsagePage:word;
    IsRange:BOOLEAN;
    IsStringRange:BOOLEAN;
    IsDesignatorRange:BOOLEAN;
    IsAbsolute:BOOLEAN;
    Reserved:array [0..9] of dword;
    case word of
      0: (
           Range:record
             UsageMin, UsageMax,
             StringMin, StringMax,
             DesignatorMin, DesignatorMax,
             DataIndexMin,   DataIndexMax : word;
           end;
         );
      1: (
           NotRange:record
             Usage,           Reserved1,
             StringIndex,     Reserved2,
             DesignatorIndex, Reserved3,
             DataIndex,       Reserved4:word;
           end;
        );
  end;

  PHIDP_BUTTON_CAPS = ^HIDP_BUTTON_CAPS;

  HIDP_VALUE_CAPS  = packed record
    UsagePage : word;
    ReportID : byte;
    IsAlias : boolean;

    BitField  : word;
    LinkCollection  : word;   // A unique internal index pointer

    LinkUsage : word;
    LinkUsagePage : word;

    IsRange : BOOLEAN ;
    IsStringRange : BOOLEAN;
    IsDesignatorRange : BOOLEAN;
    IsAbsolute : BOOLEAN;

    HasNull : BOOLEAN;        // Does this channel have a null report   union
    Reserved:byte;
    BitSize:word;        // How many bits are devoted to this value?

    ReportCount:word;    // See Note below.  Usually set to 1.
    Reserved2: array [0..4] of word;

    UnitsExp:dword;
    Units:dword;

    LogicalMin,  LogicalMax :integer;
    PhysicalMin, PhysicalMax:integer;

    case word of
      0: (
           Range:record
             UsageMin, UsageMax,
             StringMin, StringMax,
             DesignatorMin, DesignatorMax,
             DataIndexMin,   DataIndexMax : word;
           end;
         );
      1: (
           NotRange:record
             Usage,           Reserved1,
             StringIndex,     Reserved2,
             DesignatorIndex, Reserved3,
             DataIndex,       Reserved4:word;
           end;
        );
  end;

  PHIDP_VALUE_CAPS = ^HIDP_VALUE_CAPS;

  procedure HidD_GetHidGuid(var HidGuid: TGUID);
  function HidD_GetProductString(handle: THandle):string;
  function HidD_GetManufacturerString(handle:THandle):string;
  function HidD_GetSerialNumberString(handle:THandle):string;
  function HidD_GetPhysicalDescriptor(handle:THandle):string;
  function HidD_GetPreparsedData(handle:THandle):THandle;
  function HidD_GetAttributes(handle:THandle; var Attributes:HIDD_ATTRIBUTES):boolean;
  function HidP_GetCaps(apppd:THandle; var Caps:HIDP_CAPS):dword;
  function HidD_FreePreparsedData(apppd:THandle):boolean;

  function HidP_GetButtonCaps(ReportType:HIDP_REPORT_TYPE;
    ButtonCaps : pointer; var ButtonCapsLength : dword;
    PreparsedData : THandle) : dword;

  function HidP_GetValueCaps(ReportType:HIDP_REPORT_TYPE;
    ValueCaps : pointer; var ValueCapsLength : dword;
    PreparsedData : THandle) : dword;

  function HidP_MaxUsageListLength(ReportType:HIDP_REPORT_TYPE;
    usage:dword; PreparsedData : THandle) : dword;

  function HidD_GetInputReport(handle:THandle; buff:pointer; len:dword):boolean;
  function HidD_GetFeature(handle:THandle; buff:pointer; len:dword):boolean;
  function HidD_SetOutputReport(handle:THandle; buff:pointer; len:dword):boolean;
  function HidD_SetFeature(handle:THandle; buff:pointer; len:dword):boolean;
  function HidD_SetNumInputBuffers(handle:THandle; NumberBuffers:dword):boolean;
  function HidD_GetNumInputBuffers(handle:THandle; var NumberBuffers:dword):boolean;

implementation
uses sysutils;

Const
  HID_DLL_NAME = 'HID.DLL';

Var
  hHidDll : THandle = 0;

function AllocHidDll:boolean;
begin
  if hHidDll = 0 then hHidDll := LoadLibrary(HID_DLL_NAME);
  Result := (hHidDll <> 0);
end;

procedure HidD_GetHidGuid(var HidGuid: TGUID);
var p : function(var HidGuid: TGUID) : dword; stdcall;
begin
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_GetHidGuid');
     if @p <> nil then p(HidGuid);
  end;
end;

function HidD_GetCommonString(handle:THandle; aMethod:string):string;
var p : function(handle:THandle; pBuff:pointer; len:dword) : bool; stdcall;
    pBuff: PChar;
begin
  Result := '';
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, PChar(aMethod));
     if @p <> nil then begin
       pBuff := StrAlloc(2048);
       if p(handle, pBuff, 2048)
         then Result := String(WideString(PWideChar(pBuff)));
       StrDispose(pBuff);
     end;
     if Length(Result) < 3 then Result := '';
  end;
end;

function HidD_GetProductString(handle:THandle):string;
begin
  Result := HidD_GetCommonString(handle, 'HidD_GetProductString');
end;

function HidD_GetManufacturerString(handle:THandle):string;
begin
  Result := HidD_GetCommonString(handle, 'HidD_GetManufacturerString');
end;

function HidD_GetSerialNumberString(handle:THandle):string;
begin
  Result := HidD_GetCommonString(handle, 'HidD_GetSerialNumberString');
end;

function HidD_GetPhysicalDescriptor(handle:THandle):string;
begin
  Result := HidD_GetCommonString(handle, 'HidD_GetPhysicalDescriptor');
end;

function HidD_GetPreparsedData(handle:THandle):THandle;
var p : function(handle:THandle; var pd:THandle) : boolean; stdcall;
begin
  Result := 0;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_GetPreparsedData');
     if @p <> nil then p(handle, Result);
  end;
end;

function HidD_GetAttributes(handle:THandle; var Attributes:HIDD_ATTRIBUTES):boolean;
var p : function(handle:THandle; var atr:HIDD_ATTRIBUTES) : boolean; stdcall;
begin
  Result := False;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_GetAttributes');
     if @p <> nil then Result := p(handle, Attributes);
  end;
end;

function HidP_GetCaps(apppd:THandle; var Caps:HIDP_CAPS):dword;
var p : function(apppd:dword; var atr:HIDP_CAPS) : dword; stdcall;
begin
  Result := dword(HIDP_STATUS_NULL);
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidP_GetCaps');
     if @p <> nil
       then Result := p(apppd, Caps);
  end;
end;

function HidD_FreePreparsedData(apppd:THandle):boolean;
var p : function(apppd:THandle) : boolean; stdcall;
begin
  Result := False;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_FreePreparsedData');
     if @p <> nil then Result := p(apppd);
  end;
end;

function HidP_GetButtonCaps(ReportType:HIDP_REPORT_TYPE;
    ButtonCaps : pointer; var ButtonCapsLength : dword;
    PreparsedData : THandle) : dword;
var p : function(ReportType:HIDP_REPORT_TYPE;
    ButtonCaps : pointer; var ButtonCapsLength : dword;
    PreparsedData : THandle) : dword; stdcall;
begin
  Result := dword(HIDP_STATUS_NULL);
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidP_GetButtonCaps');
     if @p <> nil
       then Result := p(ReportType, ButtonCaps, ButtonCapsLength, PreparsedData);
  end;
end;

function HidP_GetValueCaps(ReportType:HIDP_REPORT_TYPE;
    ValueCaps : pointer; var ValueCapsLength : dword;
    PreparsedData : THandle) : dword;
var p : function(ReportType:HIDP_REPORT_TYPE;
    ValueCaps : pointer; var ValueCapsLength : dword;
    PreparsedData : THandle) : dword; stdcall;
begin
  Result := dword(HIDP_STATUS_NULL);
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidP_GetValueCaps');
     if @p <> nil
       then Result := p(ReportType, ValueCaps, ValueCapsLength, PreparsedData);
  end;
end;

function HidP_MaxUsageListLength(ReportType:HIDP_REPORT_TYPE;
    usage: dword; PreparsedData : THandle) : dword;
var p : function(ReportType:HIDP_REPORT_TYPE;
    usage:dword; PreparsedData : THandle) : dword; stdcall;
begin
  Result := dword(HIDP_STATUS_NULL);
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidP_MaxUsageListLength');
     if @p <> nil
       then Result := p(ReportType, usage, PreparsedData);
  end;
end;

function HidD_SetNumInputBuffers(handle:THandle; NumberBuffers:dword):boolean;
var p : function(handle:THandle; NumberBuffers:dword) : bool; stdcall;
begin
  Result := False;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_SetNumInputBuffers');
     if @p <> nil
         then Result := p(handle, NumberBuffers);
  end;
end;

function HidD_GetNumInputBuffers(handle:THandle; var NumberBuffers:dword):boolean;
var p : function(handle:THandle; var NumberBuffers:dword) : bool; stdcall;
begin
  Result := False;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, 'HidD_GetNumInputBuffers');
     if @p <> nil
         then Result := p(handle, NumberBuffers);
  end;
end;

function HidD_HidIOBuffer(handle:THandle; buff:pointer; len:dword; aMethod:string):boolean;
var p : function(handle:THandle; buff:pointer; len:dword) : bool; stdcall;
begin
  Result := False;
  if AllocHidDll then begin
     @p := GetProcAddress(hHidDll, PChar(aMethod));
     if @p <> nil
         then Result := p(handle,buff,len);
  end;
end;

function HidD_GetInputReport(handle:THandle; buff:pointer; len:dword):boolean;
begin
  Result := HidD_HidIOBuffer(handle, buff, len, 'HidD_GetInputReport');
end;

function HidD_GetFeature(handle:THandle; buff:pointer; len:dword):boolean;
begin
  Result := HidD_HidIOBuffer(handle, buff, len, 'HidD_GetFeature');
end;

function HidD_SetOutputReport(handle:THandle; buff:pointer; len:dword):boolean;
begin
  Result := HidD_HidIOBuffer(handle, buff, len, 'HidD_SetOutputReport');
end;

function HidD_SetFeature(handle:THandle; buff:pointer; len:dword):boolean;
begin
  Result := HidD_HidIOBuffer(handle, buff, len, 'HidD_SetFeature');
end;

initialization

finalization
  if hHidDll <> 0 then FreeLibrary(hHidDll);

end.
