⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hidcontrollerclass.pas

📁 Componente para Tratar USB
💻 PAS
📖 第 1 页 / 共 4 页
字号:

unit HidControllerClass;

interface

uses
  Windows, Messages, Classes, Forms, SysUtils,
  DBT, SetupAPI, Hid;

const
  // strings from the registry for CheckOutByClass
  cHidKeyboardClass = 'Keyboard';
  cHidMouseClass    = 'Mouse';
  cHidNoClass       = 'HIDClass';

type
  // forward declarations
  TJvHidDeviceController = class;
  TJvHidDevice           = class;

  // the Event function declarations
  TJvHidEnumerateEvent  = function (HidDev: TJvHidDevice; Idx: Integer): Boolean of object;
  TJvHidUnplugEvent     = procedure(HidDev: TJvHidDevice) of object;

  // the representation of a HID device

  TJvHidDevice = class(TObject)
  private
    // internal control variables
    FMyController:         TJvHidDeviceController;
    FIsPluggedIn:          Boolean;
    FIsCheckedOut:         Boolean;
    FIsEnumerated:         Boolean;
    FHidFileHandle:        THandle;
    FHidOverlappedHandle:  THandle;
    // internal properties part
    FDeviceID:             DWORD;
    FDevicePath:           string;
    FRegDescr:             string;
    FRegClass:             string;
    FVendorName:           AnsiString;
    FProductName:          AnsiString;
    FPhysicalDescriptor:   AnsiString;
    FSerialNumber:         AnsiString;
    FLanguageStrings:      TStringList;
    FPreparsedData:        PHIDPPreparsedData;
    FAttributes:           THIDDAttributes;
    FCaps:                 THIDPCaps;
    FConfiguration:        THIDDConfiguration;
    FNumInputBuffers:      Integer;
    FNumOverlappedBuffers: Integer;
    FLinkCollection:       array of THIDPLinkCollectionNode;
    FMaxDataListLength:    ULONG;
    FMaxUsageListLength:   ULONG;
    FMaxButtonListLength:  ULONG;
    FReportTypeParam:      THIDPReportType;
    FUsagePageParam:       TUsage;
    FLinkCollectionParam:  WORD;
    FUsageParam:           TUsage;
    FUnplug:               TJvHidUnplugEvent;

    // tells if access to device is allowed
    function  IsAccessible: Boolean;
    procedure GetMax;

    // internal property implementors
    function  GetDeviceString        (Idx: Byte): string;
    function  GetLinkCollectionNode  (Idx: WORD): THIDPLinkCollectionNode;
    procedure SetConfiguration       (Config: THIDDConfiguration);
    procedure SetNumInputBuffers     (const Num: Integer);
    procedure SetNumOverlappedBuffers(const Num: Integer);
    procedure SetReportTypeParam     (const ReportType: THIDPReportType);
    procedure SetUsagePageParam      (const UsagePage: TUsage);

    // Constructor is hidden! Only a TJvHidDeviceController can create a TJvHidDevice object.
    constructor Create(const DevicePath: string; const DevID: DWORD;
                       const DevDesc, ClassDesc: string;
                       Controller: TJvHidDeviceController);

  protected
    // internal property implementors
    procedure DoUnplug;
    procedure SetUnplug(const Event: TJvHidUnplugEvent);

  public
    // indexed properties
    property DeviceStrings      [Idx: Byte]: string                  read GetDeviceString;
    property LinkCollectionNodes[Idx: WORD]: THIDPLinkCollectionNode read GetLinkCollectionNode;

  published
    destructor Destroy; override;

    // methods
    procedure CloseFile;
    procedure CloseFileEx;
    function  DeviceIoControl      (IoControlCode: DWORD; InBuffer: Pointer; InSize: DWORD;
                                    OutBuffer: Pointer; OutSize: DWORD;
                                    var BytesReturned: DWORD):                      Boolean;
    function  FlushQueue:                                                           Boolean;
    function  GetButtonCaps        (ButtonCaps: PHIDPButtonCaps; var Count: WORD):  NTSTATUS;
    function  GetButtons           (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetButtonsEx         (UsageList: PUsageAndPage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetData              (DataList: PHIDPData; var DataLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetFeature           (var Report; const Size: Integer):               Boolean;
    function  GetScaledUsageValue  (var UsageValue: Integer;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetSpecificButtonCaps(ButtonCaps: PHIDPButtonCaps; var Count: WORD):  NTSTATUS;
    function  GetSpecificValueCaps (ValueCaps:  PHIDPValueCaps;  var Count: WORD):  NTSTATUS;
    function  GetUsages            (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetUsagesEx          (UsageList: PUsageAndPage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetUsageValue        (var UsageValue: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetUsageValueArray   (UsageValue: PChar; UsageValueByteLength: WORD;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  GetValueCaps         (ValueCaps:  PHIDPValueCaps;  var Count: WORD):  NTSTATUS;
    function  OpenFile:   Boolean;
    function  OpenFileEx: Boolean;
    function  SetButtons           (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  SetData              (DataList: PHIDPData; var DataLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  SetFeature           (var Report; const Size: Integer):               Boolean;
    function  SetScaledUsageValue  (UsageValue: Integer;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  SetUsages            (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  SetUsageValue        (UsageValue: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  SetUsageValueArray   (UsageValue: PChar; UsageValueByteLength: WORD;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  UnsetButtons         (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  UnsetUsages          (UsageList: PUsage; var UsageLength: ULONG;
                                    var Report; ReportLength: ULONG):               NTSTATUS;
    function  ReadFile             (var Report; ToRead:  DWORD; var BytesRead:    DWORD): Boolean;
    function  ReadFileEx           (var Report; ToRead:  DWORD;
                                    CallBack: TPROverlappedCompletionRoutine):            Boolean;
    function  WriteFile            (var Report; ToWrite: DWORD; var BytesWritten: DWORD): Boolean;
    function  WriteFileEx          (var Report; ToWrite: DWORD;
                                    CallBack: TPROverlappedCompletionRoutine):            Boolean;

    // management properties
    property Attributes:            THIDDAttributes    read FAttributes;
    property Caps:                  THIDPCaps          read FCaps;
    property Configuration:         THIDDConfiguration read FConfiguration        write SetConfiguration;
    property DevicePath:            string             read FDevicePath;
    property DeviceID:              DWORD              read FDeviceID;
    property HidFileHandle:         THandle            read FHidFileHandle;
    property HidOverlappedHandle:   THandle            read FHidOverlappedHandle;
    property IsCheckedOut:          Boolean            read FIsCheckedOut;
    property IsPluggedIn:           Boolean            read FIsPluggedIn;
    property LanguageStrings:       TStringList        read FLanguageStrings;
    property LinkCollectionParam:   WORD               read FLinkCollectionParam  write FLinkCollectionParam;
    property MaxButtonListLength:   ULONG              read FMaxButtonListLength;
    property MaxDataListLength:     ULONG              read FMaxDataListLength;
    property MaxUsageListLength:    ULONG              read FMaxUsageListLength;
    property NumInputBuffers:       Integer            read FNumInputBuffers      write SetNumInputBuffers;
    property NumOverlappedBuffers:  Integer            read FNumOverlappedBuffers write SetNumOverlappedBuffers;
    property PhysicalDescriptor:    string             read FPhysicalDescriptor;
    property PreparsedData:         PHIDPPreparsedData read FPreparsedData;
    property ProductName:           string             read FProductName;
    property RegClass:              string             read FRegClass;
    property RegDescr:              string             read FRegDescr;
    property ReportTypeParam:       THIDPReportType    read FReportTypeParam      write SetReportTypeParam;
    property SerialNumber:          string             read FSerialNumber;
    property VendorName:            string             read FVendorName;
    property UsageParam:            TUsage             read FUsageParam           write FUsageParam;
    property UsagePageParam:        TUsage             read FUsagePageParam       write SetUsagePageParam;
    // the only event property
    property OnUnplug:              TJvHidUnplugEvent  read FUnplug               write SetUnplug;
  end;

  // controller class to manage all HID devices

  TJvHidDeviceController = class(TComponent)
  private
    // internal properties part
    FHidGuid:              TGUID;
    FDeviceChangeEvent:    TNotifyEvent;
    FDeviceChangeFired:    Boolean;
    FEnumerateEvent:       TJvHidEnumerateEvent;
    FDevUnplugEvent:       TJvHidUnplugEvent;
    // internal list of all HID device objects
    FList:                 TList;
    // counters for the list
    FNumCheckedInDevices:  Integer;
    FNumCheckedOutDevices: Integer;
    FNumUnpluggedDevices:  Integer;
    // internal worker functions
    function  CheckThisOut(var HidDev: TJvHidDevice; Idx: Integer; Check: Boolean): Boolean;
    procedure FillInList  (var List: TList);
    function  EventPipe   (var Msg: TMessage): Boolean;

  protected
    procedure Loaded; override;
    // internal property implementors
    procedure DoDeviceChange;
    function  DoEnumerate         (HidDev: TJvHidDevice; Idx: Integer): Boolean;
    procedure SetDeviceChangeEvent(const Notifier:   TNotifyEvent);
    procedure SetEnumerate        (const Enumerator: TJvHidEnumerateEvent);
    procedure SetDevUnplug        (const Unplugger:  TJvHidUnplugEvent);

  published
    // normal constructor/destructor
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy;                    override;

    // methods to hand out HID device objects
    procedure CheckIn              (var HidDev: TJvHidDevice);
    function  CheckOut             (var HidDev: TJvHidDevice):                       Boolean;
    function  CheckOutByClass      (var HidDev: TJvHidDevice; ClassName:   string):  Boolean;
    function  CheckOutByID         (var HidDev: TJvHidDevice; Vid, Pid:    Integer): Boolean;
    function  CheckOutByIndex      (var HidDev: TJvHidDevice; const Idx:   Integer): Boolean;
    function  CheckOutByProductName(var HidDev: TJvHidDevice; ProductName: string):  Boolean;
    function  CheckOutByVendorName (var HidDev: TJvHidDevice; VendorName:  string):  Boolean;
    // iterate over the HID devices
    function  Enumerate: Integer;

    // just to be complete the GUID
    property  HidGuid:        TGUID                read FHidGuid;
    property  NumCheckedInDevices:  Integer        read FNumCheckedInDevices;
    property  NumCheckedOutDevices: Integer        read FNumCheckedOutDevices;
    property  NumUnpluggedDevices:  Integer        read FNumUnpluggedDevices;
    // this event is copied to TJvHidDeviceOnUnplug on creation
    property  OnDeviceUnplug: TJvHidUnplugEvent    read FDevUnplugEvent    write SetDevUnplug;
    // the iterator event
    property  OnEnumerate:    TJvHidEnumerateEvent read FEnumerateEvent    write SetEnumerate;
    // the central event for HID device changes
    property  OnDeviceChange: TNotifyEvent         read FDeviceChangeEvent write SetDeviceChangeEvent;
  end;

// helpers to check the HID function and method results
function HidCheck(const RetVal: NTSTATUS): NTSTATUS; overload;
function HidCheck(const RetVal: LongBool): LongBool; overload;
function HidError(const RetVal: NTSTATUS): NTSTATUS;

// to register the component in the palette
procedure Register;

implementation

{$R HidControllerClass.dcr}

type
  EControllerError = class(Exception);
  EHidClientError  = class(Exception);

var
  // counter to prevent a second TJvHidDeviceController instance
  GlobalInstanceCount: Integer = 0;

//== these are declared inconsistent in Windows.pas ===================

function ReadFileEx(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD;
  var Overlapped: TOverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;
  external 'kernel32.dll' name 'ReadFileEx';
function WriteFileEx(hFile: THandle; var Buffer; nNumberOfBytesToWrite: DWORD;
  var Overlapped: TOverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;
 external 'kernel32.dll' name 'WriteFileEx';

//== TJvHidDevice =====================================================

// internal helper to read string values from a devices registry area

function GetRegistryProperty(PnPHandle: HDEVINFO; var DevData: TSPDevInfoData; ClassID: DWORD): string;
var
  BytesReturned: DWORD;
  RegData:       DWORD;
  Buffer:        array [0..256] of Char;
begin
  BytesReturned := 0;
  RegData       := REG_SZ;
  Buffer[0]     := #0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, ClassID,
    @RegData, @Buffer[0], SizeOf(Buffer), @BytesReturned);
  Result := Buffer;
end;

//-- TJvHidDevice: basics and internals -------------------------------

// create and fill in a HidDevice object
// the constructor is only accessible from TJvHidController
// DevicePath names the device "file"
// DevID is a handle to the individual device
// (differs even for two devices of the same kind)
// DevDesc and ClassDesc are two strings from the devices registry space
// Controller is the devices controller object

constructor TJvHidDevice.Create(const DevicePath: string; const DevID: DWORD;
  const DevDesc, ClassDesc: string; Controller: TJvHidDeviceController);
var
  I:      Integer;
  Len:    ULONG;
  Buffer: array [0..256] of WideChar;
  IDs:    array [0..258] of WORD;
  Name:   array [0..256] of Char;
begin
  inherited Create;

  // initialize private data
  FMyController         := Controller;
  FIsPluggedIn          := True;
  FIsCheckedOut         := False;
  FIsEnumerated         := False;
  FHidOverlappedHandle  := INVALID_HANDLE_VALUE;
  FDeviceID             := 0;
  FDevicePath           := DevicePath;
  FRegDescr             := '';
  FRegClass             := '';
  FVendorName           := '';
  FProductName          := '';
  FPhysicalDescriptor   := '';
  FSerialNumber         := '';
  FLanguageStrings      := TStringList.Create;
  FPreparsedData        := 0;
  FillChar(FCaps, SizeOf(FCaps), #0);
  FillChar(FConfiguration, SizeOf(FConfiguration), #0);
  FNumInputBuffers      := 0;
  FNumOverlappedBuffers := 0;
  SetLength(FLinkCollection, 0);
  FMaxDataListLength    := 0;
  FMaxUsageListLength   := 0;
  FMaxButtonListLength  := 0;
  FReportTypeParam      := HIDP_Input;
  FUsagePageParam       := 0;
  FLinkCollectionParam  := 0;
  FUsageParam           := 0;
  FUnplug               := Controller.FDevUnplugEvent;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -