eventpipe源码分析

在这里插入图片描述

首先我们看eventhandler的注册函数

void evhandler_register(evhandler_t *evh) {
	evh->type = next_type++;
	//向queue中添加对应的handler
	TAILQ_INSERT_TAIL(&evh_list, evh, node);
}

然后我们看一下关于事件处理对应的逻辑, 函数的参数是事件

static int event_handle(event_t *ev, size_t size) {
	evhandler_t *evh;
	//首先根据对应的类型查找对应的事件handler
	evh = evhandler_find(ev->type);
	//调用处理函数
	return evh->handle(ev, evh->priv);
}

下面这个函数是事件管道的初始化函数

  • 首先我们获取对应的CPU核心数量, 这个主要通过sysconf这个函数来做的,
  • 然后我们根据对应的CPU核心数量去分配内存, 分配的内存主要用于拉取对应的事件,和对应的事件。
  • 其次ebpf内核模块通过perf_event向用户态程序发送消息,需要使用一种特殊的map BPF_MAP_TYPE_PERF_EVENT_ARRAY,我们使用bpf_map_create进行创建
  • 然后队列的初始化函数这个函数,我们会使用对应的perf_open函数来完成相应操作
int evpipe_init(evpipe_t *evp, size_t qsize) {
	uint32_t cpu;
	int err;

	if (G.dump) {
		evp->mapfd = 0xeeee;
		return 0;
	}
    //首先获取系统的cpu核心数量
	evp->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
    //创建一个性能事件数组
	evp->mapfd = bpf_map_create(BPF_MAP_TYPE_PERF_EVENT_ARRAY,
				    sizeof(uint32_t), sizeof(int), evp->ncpus);
	//首先根据cpu核心数量分配对应队列的内存
	evp->q = calloc(evp->ncpus, sizeof(*evp->q));
	evp->poll = calloc(evp->ncpus, sizeof(*evp->poll));
	//创建对应数量的队列
	for (cpu = 0; cpu < evp->ncpus; cpu++) {
		//创建队列
		err = evqueue_init(evp, cpu, qsize);
	}
}

首先ebpf map位于内核态,如果想通知对应的信息给用户,那么就必须借助对应的perf_event,perf是 linux 内核提供的一项与用户进行交互的机制,主要用于内核机制的监视分析, 这是一种软件事件, 同时是用于对应的 bpf 输出。

attr.type          = PERF_TYPE_SOFTWARE;
attr.config        = PERF_COUNT_SW_BPF_OUTPUT;
attr.sample_type   = PERF_SAMPLE_RAW;
attr.wakeup_events = 1;

然后更新对应的id, 通过这种索引关系,我们可以根据所用下标获取对应的perf_event

bpf_map_update(evp->mapfd, &cpu, &q->fd, BPF_ANY);

然后分配对应性能映射内存

  • sysconf(_SC_PAGESIZE):这个调用用来获取系统的页面大小,这通常是内存映射操作需要考虑的一个参数。
  • size += sysconf(_SC_PAGESIZE);:这行代码将当前的size变量增加页面大小,可能是为了确保分配足够的内存。
  • q->mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, q->fd, 0);:这行代码尝试将文件描述符q->fd指向的文件映射到内存中。PROT_READ | PROT_WRITE指定了映射区域的保护属性,允许读写访问。MAP_SHARED表示映射是共享的,对映射区域的修改将反映到文件上。
int evqueue_init(evpipe_t *evp, uint32_t cpu, size_t size) {
	//首先定义一个性能事件的结构体
	struct perf_event_attr attr = { 0 };
	//根据cpu号查询对应队列
	struct evqueue *q = &evp->q[cpu];
	int err;
	//设置对应的属性, 分别是软件事件
	attr.type          = PERF_TYPE_SOFTWARE;
	attr.config        = PERF_COUNT_SW_BPF_OUTPUT;
	attr.sample_type   = PERF_SAMPLE_RAW;
	attr.wakeup_events = 1;
    //打开一个性能事件, 这个事件用于创建对应性能事件队列
	q->fd = perf_event_open(&attr, -1, cpu, -1, 0);
	//更新bpf的map值, 它的键是cpu号码, 它的值是创建的队列
	err = bpf_map_update(evp->mapfd, &cpu, &q->fd, BPF_ANY);
	
	size += sysconf(_SC_PAGESIZE);
	//分配对应的内存
	q->mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, q->fd, 0);
	evp->poll[cpu].fd     = q->fd;
	evp->poll[cpu].events = POLLIN;
	return 0;
}

有了这些基础的配置, 我们就可以通过事件循环来不断的拉取对应的事件了, 关于这点且听下回分解

关于控件的用法,你提供的代码大部分都是错误的,我把JvHidControllerClass.pas中函数及变量定义部分的内容给你: unit JvHidControllerClass; {$DEFINE DEFAULT_JVCL_INC} {$I jvcl.inc} {$I windowsonly.inc} interface uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} Windows, Messages, Classes, SysUtils, JvComponentBase, DBT, SetupApi, Hid, JvTypes; const // a version string for the component cHidControllerClassVersion = '1.0.35'; // strings from the registry for CheckOutByClass cHidNoClass = 'HIDClass'; type // forward declarations TJvHidDeviceController = class; TJvHidDevice = class; // the Event function declarations TJvHidEnumerateEvent = function(HidDev: TJvHidDevice; const Idx: Integer): Boolean of object; TJvHidPlugEvent = procedure(HidDev: TJvHidDevice) of object; TJvHidUnplugEvent = TJvHidPlugEvent; TJvHidDataEvent = procedure(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word) of object; TJvHidDataErrorEvent = procedure(HidDev: TJvHidDevice; Error: DWORD) of object; // check out test function TJvHidCheckCallback = function(HidDev: TJvHidDevice): Boolean; stdcall; // open overlapped read or write file handle TJvHidOpenExMode = (omhRead, omhWrite); // the physical descriptor TJvPhysicalDescriptor = array of WORD; // all USB relevant driver entries in the registry TJvHidPnPInfo = class(TObject) private FDeviceID: DWORD; FDevicePath: string; FCapabilities: DWORD; FClassDescr: string; FClassGUID: string; FCompatibleIDs: TStringList; FConfigFlags: DWORD; FDeviceDescr: string; FDriver: string; FFriendlyName: string; FHardwareID: TStringList; FLowerFilters: TStringList; FMfg: string; FUpperFilters: TStringList; FAddress: string; FBusNumber: DWORD; FBusType: string; FCharacteristics: string; FDevType: DWORD; FEnumeratorName: string; FExclusive: DWORD; FLegacyBusType: DWORD; FLocationInfo: string; FPhysDevObjName: string; FSecuritySDS: string; FService: string; FUINumber: DWORD; FUINumberFormat: string; function GetRegistryPropertyString(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): string; function GetRegistryPropertyStringList(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): TStringList; function GetRegistryPropertyDWord(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): DWORD; function GetCompatibleIDs: TStrings; function GetHardwareID: TStrings; function GetLowerFilters: TStrings; function GetUpperFilters: TStrings; public property DeviceID: DWORD read FDeviceID; property DevicePath: string read FDevicePath; // registry values property Capabilities: DWORD read FCapabilities; property ClassDescr: string read FClassDescr; property ClassGUID: string read FClassGUID; property CompatibleIDs: TStrings read GetCompatibleIDs; property ConfigFlags: DWORD read FConfigFlags; property DeviceDescr: string read FDeviceDescr; property Driver: string read FDriver; property FriendlyName: string read FFriendlyName; property HardwareID: TStrings read GetHardwareID; property LowerFilters: TStrings read GetLowerFilters; property Mfg: string read FMfg; property UpperFilters: TStrings read GetUpperFilters; property Address: string read FAddress; property BusNumber: DWORD read FBusNumber; property BusType: string read FBusType; property Characteristics: string read FCharacteristics; property DevType: DWORD read FDevType; property EnumeratorName: string read FEnumeratorName; property Exclusive: DWORD read FExclusive; property LegacyBusType: DWORD read FLegacyBusType; property LocationInfo: string read FLocationInfo; property PhysDevObjName: string read FPhysDevObjName; property SecuritySDS: string read FSecuritySDS; property Service: string read FService; property UINumber: DWORD read FUINumber; property UINumberFormat: string read FUINumberFormat; constructor Create(APnPHandle: HDEVINFO; ADevData: TSPDevInfoData; ADevicePath: PChar); destructor Destroy; override; end; // a thread helper class to implement TJvHidDevice.OnData TJvHidDeviceReadThread = class(TJvCustomThread) private FErr: DWORD; procedure DoData; procedure DoDataError; constructor CtlCreate(const Dev: TJvHidDevice); protected procedure Execute; override; public Device: TJvHidDevice; NumBytesRead: Cardinal; Report: array of Byte; constructor Create(CreateSuspended: Boolean); end; // the representation of a HID device TJvHidDevice = class(TObject) private // internal control variables FMyController: TJvHidDeviceController; FIsPluggedIn: Boolean; FIsCheckedOut: Boolean; FIsEnumerated: Boolean; FHidFileHandle: THandle; FHidOverlappedRead: THandle; FHidOverlappedWrite: THandle; FOvlRead: TOverlapped; FOvlWrite: TOverlapped; // internal properties part FAttributes: THIDDAttributes; FPnPInfo: TJvHidPnPInfo; FVendorName: WideString; FProductName: WideString; FPhysicalDescriptor: TJvPhysicalDescriptor; FPreparsedData: PHIDPPreparsedData; FSerialNumber: WideString; FLanguageStrings: TStringList; FNumInputBuffers: Integer; FNumOverlappedBuffers: Integer; FThreadSleepTime: Integer; FLinkCollection: array of THIDPLinkCollectionNode; FMaxDataListLength: ULONG; FMaxUsageListLength: ULONG; FMaxButtonListLength: ULONG; FReportTypeParam: THIDPReportType; FUsagePageParam: TUsage; FLinkCollectionParam: WORD; FUsageParam: TUsage; FData: TJvHidDataEvent; FDataError: TJvHidDataErrorEvent; FUnplug: TJvHidUnplugEvent; FHasReadWriteAccess: Boolean; FDataThread: TJvHidDeviceReadThread; FTag: Integer; // tells if access to device is allowed function IsAccessible: Boolean; procedure GetMax; // internal property implementors function GetDeviceStringAnsi(Idx: Byte): string; function GetDeviceStringUnicode(Idx: Byte): WideString; function GetLinkCollectionNode(Idx: WORD): THIDPLinkCollectionNode; function GetConfiguration: THIDDConfiguration; function GetPreparsedData: PHIDPPreparsedData; function GetCaps: THIDPCaps; function GetVendorName: WideString; function GetProductName: WideString; function GetSerialNumber: WideString; function GetPhysicalDescriptor: TJvPhysicalDescriptor; function GetLanguageStrings: TStrings; function GetOverlappedReadResult: DWORD; function GetOverlappedWriteResult: DWORD; procedure SetConfiguration(const Config: THIDDConfiguration); procedure SetDataEvent(const DataEvent: TJvHidDataEvent); procedure SetNumInputBuffers(const Num: Integer); procedure SetNumOverlappedBuffers(const Num: Integer); procedure SetReportTypeParam(const ReportType: THIDPReportType); procedure SetThreadSleepTime(const SleepTime: Integer); procedure SetUsagePageParam(const UsagePage: TUsage); procedure StartThread; procedure StopThread; // Constructor is hidden! Only a TJvHidDeviceController can create a TJvHidDevice object. // APnPInfo becomes the property of this class, do not try to free it yourself, // even if this call raises an exception. // The destructor of this class will take care of the cleanup even when an exception // is raised (as specified by the Delphi language) constructor CtlCreate(const APnPInfo: TJvHidPnPInfo; const Controller: TJvHidDeviceController); protected // internal event implementor procedure DoUnplug; public // dummy constructor constructor Create; destructor Destroy; override; // methods function CancelIO(const Mode: TJvHidOpenExMode): Boolean; procedure CloseFile; procedure CloseFileEx(const Mode: TJvHidOpenExMode); 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: PAnsiChar; UsageValueByteLength: WORD; var Report; ReportLength: ULONG): NTSTATUS; function GetValueCaps(ValueCaps: PHIDPValueCaps; var Count: WORD): NTSTATUS; function OpenFile: Boolean; function OpenFileEx(Mode: TJvHidOpenExMode): 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: PAnsiChar; 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; function CheckOut: Boolean; // Windows version dependent methods // added in Win 2000 function GetExtendedAttributes(ReportType: THIDPReportType; DataIndex: Word; Attributes: PHIDPExtendedAttributes; var LengthAttributes: ULONG): NTSTATUS; function InitializeReportForID(ReportType: THIDPReportType; ReportID: Byte; var Report; ReportLength: ULONG): NTSTATUS; // added in Win XP function GetInputReport(var Report; const Size: ULONG): Boolean; function SetOutputReport(var Report; const Size: ULONG): Boolean; // read only properties property Attributes: THIDDAttributes read FAttributes; property Caps: THIDPCaps read GetCaps; property HasReadWriteAccess: Boolean read FHasReadWriteAccess; property HidFileHandle: THandle read FHidFileHandle; property HidOverlappedRead: THandle read FHidOverlappedRead; property HidOverlappedWrite: THandle read FHidOverlappedWrite; property HidOverlappedReadResult: DWORD read GetOverlappedReadResult; property HidOverlappedWriteResult: DWORD read GetOverlappedWriteResult; property IsCheckedOut: Boolean read FIsCheckedOut; property IsPluggedIn: Boolean read FIsPluggedIn; property LanguageStrings: TStrings read GetLanguageStrings; property MaxButtonListLength: ULONG read FMaxButtonListLength; property MaxDataListLength: ULONG read FMaxDataListLength; property MaxUsageListLength: ULONG read FMaxUsageListLength; property PhysicalDescriptor: TJvPhysicalDescriptor read GetPhysicalDescriptor; property PnPInfo: TJvHidPnPInfo read FPnPInfo; property PreparsedData: PHIDPPreparsedData read GetPreparsedData; property ProductName: WideString read GetProductName; property SerialNumber: WideString read GetSerialNumber; property VendorName: WideString read GetVendorName; // read write properties property Configuration: THIDDConfiguration read GetConfiguration write SetConfiguration; property LinkCollectionParam: WORD read FLinkCollectionParam write FLinkCollectionParam; property NumInputBuffers: Integer read FNumInputBuffers write SetNumInputBuffers; property NumOverlappedBuffers: Integer read FNumOverlappedBuffers write SetNumOverlappedBuffers; property ReportTypeParam: THIDPReportType read FReportTypeParam write SetReportTypeParam; property Tag: Integer read FTag write FTag; property ThreadSleepTime: Integer read FThreadSleepTime write SetThreadSleepTime; property UsagePageParam: TUsage read FUsagePageParam write SetUsagePageParam; property UsageParam: TUsage read FUsageParam write FUsageParam; // indexed properties property DeviceStrings[Idx: Byte]: string read GetDeviceStringAnsi; property DeviceStringsUnicode[Idx: Byte]: WideString read GetDeviceStringUnicode; property LinkCollectionNodes[Idx: WORD]: THIDPLinkCollectionNode read GetLinkCollectionNode; // event properties property OnData: TJvHidDataEvent read FData write SetDataEvent; property OnDataError: TJvHidDataErrorEvent read FDataError write FDataError; property OnUnplug: TJvHidUnplugEvent read FUnplug write FUnplug; end; // controller class to manage all HID devices {$IFDEF RTL230_UP} [ComponentPlatformsAttribute(pidWin32 or pidWin64)] {$ENDIF RTL230_UP} TJvHidDeviceController = class(TJvComponent) private // internal properties part FHidGuid: TGUID; FArrivalEvent: TJvHidPlugEvent; FDeviceChangeEvent: TNotifyEvent; FEnumerateEvent: TJvHidEnumerateEvent; FDevDataEvent: TJvHidDataEvent; FDevDataErrorEvent: TJvHidDataErrorEvent; FDevUnplugEvent: TJvHidUnplugEvent; FRemovalEvent: TJvHidUnplugEvent; FDevThreadSleepTime: Integer; FVersion: string; FDummy: string; // internal list of all HID device objects FList: TList; // counters for the list FNumCheckedInDevices: Integer; FNumCheckedOutDevices: Integer; FNumUnpluggedDevices: Integer; // reentrancy FInDeviceChange: Boolean; FLParam: LPARAM; // window to catch WM_DEVICECHANGE FHWnd: HWND; // internal worker functions function CheckThisOut(var HidDev: TJvHidDevice; Idx: Integer; Check: Boolean): Boolean; procedure EventPipe(var Msg: TMessage); // internal event implementors procedure SetDeviceChangeEvent(const Notifier: TNotifyEvent); procedure SetEnumerate(const Enumerator: TJvHidEnumerateEvent); procedure SetDevThreadSleepTime(const DevTime: Integer); procedure SetDevData(const DataEvent: TJvHidDataEvent); procedure SetDevDataError(const DataErrorEvent: TJvHidDataErrorEvent); procedure SetDevUnplug(const Unplugger: TJvHidUnplugEvent); protected procedure DoArrival(HidDev: TJvHidDevice); procedure DoRemoval(HidDev: TJvHidDevice); procedure DoDeviceChange; function DoEnumerate(HidDev: TJvHidDevice; Idx: Integer): Boolean; public // 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; const ClassName: string): Boolean; function CheckOutByID(var HidDev: TJvHidDevice; const Vid, Pid: Integer): Boolean; function CheckOutByIndex(var HidDev: TJvHidDevice; const Idx: Integer): Boolean; function CheckOutByProductName(var HidDev: TJvHidDevice; const ProductName: WideString): Boolean; function CheckOutByVendorName(var HidDev: TJvHidDevice; const VendorName: WideString): Boolean; function CheckOutByCallback(var HidDev: TJvHidDevice; Check: TJvHidCheckCallback): Boolean; // methods to count HID device objects function CountByClass(const ClassName: string): Integer; function CountByID(const Vid, Pid: Integer): Integer; function CountByProductName(const ProductName: WideString): Integer; function CountByVendorName(const VendorName: WideString): Integer; function CountByCallback(Check: TJvHidCheckCallback): Integer; // iterate over the HID devices function Enumerate: Integer; class function HidVersion: string; // 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; published property DevThreadSleepTime: Integer read FDevThreadSleepTime write SetDevThreadSleepTime default 100; property Version: string read FVersion write FDummy stored False; property OnArrival: TJvHidPlugEvent read FArrivalEvent write FArrivalEvent; // the iterator event property OnEnumerate: TJvHidEnumerateEvent read FEnumerateEvent write SetEnumerate; // the central event for HID device changes property OnDeviceChange: TNotifyEvent read FDeviceChangeEvent write SetDeviceChangeEvent; // these events are copied to TJvHidDevices on creation property OnDeviceData: TJvHidDataEvent read FDevDataEvent write SetDevData; property OnDeviceDataError: TJvHidDataErrorEvent read FDevDataErrorEvent write SetDevDataError; property OnDeviceUnplug: TJvHidUnplugEvent read FDevUnplugEvent write SetDevUnplug; property OnRemoval: TJvHidUnplugEvent read FRemovalEvent write FRemovalEvent; // to be callable at design time procedure DeviceChange; 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; function HidErrorString(const RetVal: NTSTATUS): string; // to register the component in the palette procedure Register; {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_45/run/JvHidControllerClass.pas $'; Revision: '$Revision: 13102 $'; Date: '$Date: 2011-09-07 07:46:34 +0200 (mer., 07 sept. 2011) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} implementation ====== 你仔细分析查看,用对控件!
09-23
新代码编译出错一大堆: 首先,控件引用的是JvHidControllerClass,不是JvHidController。下面是JvHidControllerClass.pas文件前面的定义变量或函数,请正确使用,特别要注意签名问题。不一致会导致编译报错!请修改HidDeviceUnit.pas。 unit JvHidControllerClass; {$DEFINE DEFAULT_JVCL_INC} {$I jvcl.inc} {$I windowsonly.inc} interface uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} Windows, Messages, Classes, SysUtils, JvComponentBase, DBT, SetupApi, Hid, JvTypes; const // a version string for the component cHidControllerClassVersion = '1.0.35'; // strings from the registry for CheckOutByClass cHidNoClass = 'HIDClass'; type // forward declarations TJvHidDeviceController = class; TJvHidDevice = class; // the Event function declarations TJvHidEnumerateEvent = function(HidDev: TJvHidDevice; const Idx: Integer): Boolean of object; TJvHidPlugEvent = procedure(HidDev: TJvHidDevice) of object; TJvHidUnplugEvent = TJvHidPlugEvent; TJvHidDataEvent = procedure(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word) of object; TJvHidDataErrorEvent = procedure(HidDev: TJvHidDevice; Error: DWORD) of object; // check out test function TJvHidCheckCallback = function(HidDev: TJvHidDevice): Boolean; stdcall; // open overlapped read or write file handle TJvHidOpenExMode = (omhRead, omhWrite); // the physical descriptor TJvPhysicalDescriptor = array of WORD; // all USB relevant driver entries in the registry TJvHidPnPInfo = class(TObject) private FDeviceID: DWORD; FDevicePath: string; FCapabilities: DWORD; FClassDescr: string; FClassGUID: string; FCompatibleIDs: TStringList; FConfigFlags: DWORD; FDeviceDescr: string; FDriver: string; FFriendlyName: string; FHardwareID: TStringList; FLowerFilters: TStringList; FMfg: string; FUpperFilters: TStringList; FAddress: string; FBusNumber: DWORD; FBusType: string; FCharacteristics: string; FDevType: DWORD; FEnumeratorName: string; FExclusive: DWORD; FLegacyBusType: DWORD; FLocationInfo: string; FPhysDevObjName: string; FSecuritySDS: string; FService: string; FUINumber: DWORD; FUINumberFormat: string; function GetRegistryPropertyString(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): string; function GetRegistryPropertyStringList(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): TStringList; function GetRegistryPropertyDWord(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): DWORD; function GetCompatibleIDs: TStrings; function GetHardwareID: TStrings; function GetLowerFilters: TStrings; function GetUpperFilters: TStrings; public property DeviceID: DWORD read FDeviceID; property DevicePath: string read FDevicePath; // registry values property Capabilities: DWORD read FCapabilities; property ClassDescr: string read FClassDescr; property ClassGUID: string read FClassGUID; property CompatibleIDs: TStrings read GetCompatibleIDs; property ConfigFlags: DWORD read FConfigFlags; property DeviceDescr: string read FDeviceDescr; property Driver: string read FDriver; property FriendlyName: string read FFriendlyName; property HardwareID: TStrings read GetHardwareID; property LowerFilters: TStrings read GetLowerFilters; property Mfg: string read FMfg; property UpperFilters: TStrings read GetUpperFilters; property Address: string read FAddress; property BusNumber: DWORD read FBusNumber; property BusType: string read FBusType; property Characteristics: string read FCharacteristics; property DevType: DWORD read FDevType; property EnumeratorName: string read FEnumeratorName; property Exclusive: DWORD read FExclusive; property LegacyBusType: DWORD read FLegacyBusType; property LocationInfo: string read FLocationInfo; property PhysDevObjName: string read FPhysDevObjName; property SecuritySDS: string read FSecuritySDS; property Service: string read FService; property UINumber: DWORD read FUINumber; property UINumberFormat: string read FUINumberFormat; constructor Create(APnPHandle: HDEVINFO; ADevData: TSPDevInfoData; ADevicePath: PChar); destructor Destroy; override; end; // a thread helper class to implement TJvHidDevice.OnData TJvHidDeviceReadThread = class(TJvCustomThread) private FErr: DWORD; procedure DoData; procedure DoDataError; constructor CtlCreate(const Dev: TJvHidDevice); protected procedure Execute; override; public Device: TJvHidDevice; NumBytesRead: Cardinal; Report: array of Byte; constructor Create(CreateSuspended: Boolean); end; // the representation of a HID device TJvHidDevice = class(TObject) private // internal control variables FMyController: TJvHidDeviceController; FIsPluggedIn: Boolean; FIsCheckedOut: Boolean; FIsEnumerated: Boolean; FHidFileHandle: THandle; FHidOverlappedRead: THandle; FHidOverlappedWrite: THandle; FOvlRead: TOverlapped; FOvlWrite: TOverlapped; // internal properties part FAttributes: THIDDAttributes; FPnPInfo: TJvHidPnPInfo; FVendorName: WideString; FProductName: WideString; FPhysicalDescriptor: TJvPhysicalDescriptor; FPreparsedData: PHIDPPreparsedData; FSerialNumber: WideString; FLanguageStrings: TStringList; FNumInputBuffers: Integer; FNumOverlappedBuffers: Integer; FThreadSleepTime: Integer; FLinkCollection: array of THIDPLinkCollectionNode; FMaxDataListLength: ULONG; FMaxUsageListLength: ULONG; FMaxButtonListLength: ULONG; FReportTypeParam: THIDPReportType; FUsagePageParam: TUsage; FLinkCollectionParam: WORD; FUsageParam: TUsage; FData: TJvHidDataEvent; FDataError: TJvHidDataErrorEvent; FUnplug: TJvHidUnplugEvent; FHasReadWriteAccess: Boolean; FDataThread: TJvHidDeviceReadThread; FTag: Integer; // tells if access to device is allowed function IsAccessible: Boolean; procedure GetMax; // internal property implementors function GetDeviceStringAnsi(Idx: Byte): string; function GetDeviceStringUnicode(Idx: Byte): WideString; function GetLinkCollectionNode(Idx: WORD): THIDPLinkCollectionNode; function GetConfiguration: THIDDConfiguration; function GetPreparsedData: PHIDPPreparsedData; function GetCaps: THIDPCaps; function GetVendorName: WideString; function GetProductName: WideString; function GetSerialNumber: WideString; function GetPhysicalDescriptor: TJvPhysicalDescriptor; function GetLanguageStrings: TStrings; function GetOverlappedReadResult: DWORD; function GetOverlappedWriteResult: DWORD; procedure SetConfiguration(const Config: THIDDConfiguration); procedure SetDataEvent(const DataEvent: TJvHidDataEvent); procedure SetNumInputBuffers(const Num: Integer); procedure SetNumOverlappedBuffers(const Num: Integer); procedure SetReportTypeParam(const ReportType: THIDPReportType); procedure SetThreadSleepTime(const SleepTime: Integer); procedure SetUsagePageParam(const UsagePage: TUsage); procedure StartThread; procedure StopThread; // Constructor is hidden! Only a TJvHidDeviceController can create a TJvHidDevice object. // APnPInfo becomes the property of this class, do not try to free it yourself, // even if this call raises an exception. // The destructor of this class will take care of the cleanup even when an exception // is raised (as specified by the Delphi language) constructor CtlCreate(const APnPInfo: TJvHidPnPInfo; const Controller: TJvHidDeviceController); protected // internal event implementor procedure DoUnplug; public // dummy constructor constructor Create; destructor Destroy; override; // methods function CancelIO(const Mode: TJvHidOpenExMode): Boolean; procedure CloseFile; procedure CloseFileEx(const Mode: TJvHidOpenExMode); 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: PAnsiChar; UsageValueByteLength: WORD; var Report; ReportLength: ULONG): NTSTATUS; function GetValueCaps(ValueCaps: PHIDPValueCaps; var Count: WORD): NTSTATUS; function OpenFile: Boolean; function OpenFileEx(Mode: TJvHidOpenExMode): 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: PAnsiChar; 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; function CheckOut: Boolean; // Windows version dependent methods // added in Win 2000 function GetExtendedAttributes(ReportType: THIDPReportType; DataIndex: Word; Attributes: PHIDPExtendedAttributes; var LengthAttributes: ULONG): NTSTATUS; function InitializeReportForID(ReportType: THIDPReportType; ReportID: Byte; var Report; ReportLength: ULONG): NTSTATUS; // added in Win XP function GetInputReport(var Report; const Size: ULONG): Boolean; function SetOutputReport(var Report; const Size: ULONG): Boolean; // read only properties property Attributes: THIDDAttributes read FAttributes; property Caps: THIDPCaps read GetCaps; property HasReadWriteAccess: Boolean read FHasReadWriteAccess; property HidFileHandle: THandle read FHidFileHandle; property HidOverlappedRead: THandle read FHidOverlappedRead; property HidOverlappedWrite: THandle read FHidOverlappedWrite; property HidOverlappedReadResult: DWORD read GetOverlappedReadResult; property HidOverlappedWriteResult: DWORD read GetOverlappedWriteResult; property IsCheckedOut: Boolean read FIsCheckedOut; property IsPluggedIn: Boolean read FIsPluggedIn; property LanguageStrings: TStrings read GetLanguageStrings; property MaxButtonListLength: ULONG read FMaxButtonListLength; property MaxDataListLength: ULONG read FMaxDataListLength; property MaxUsageListLength: ULONG read FMaxUsageListLength; property PhysicalDescriptor: TJvPhysicalDescriptor read GetPhysicalDescriptor; property PnPInfo: TJvHidPnPInfo read FPnPInfo; property PreparsedData: PHIDPPreparsedData read GetPreparsedData; property ProductName: WideString read GetProductName; property SerialNumber: WideString read GetSerialNumber; property VendorName: WideString read GetVendorName; // read write properties property Configuration: THIDDConfiguration read GetConfiguration write SetConfiguration; property LinkCollectionParam: WORD read FLinkCollectionParam write FLinkCollectionParam; property NumInputBuffers: Integer read FNumInputBuffers write SetNumInputBuffers; property NumOverlappedBuffers: Integer read FNumOverlappedBuffers write SetNumOverlappedBuffers; property ReportTypeParam: THIDPReportType read FReportTypeParam write SetReportTypeParam; property Tag: Integer read FTag write FTag; property ThreadSleepTime: Integer read FThreadSleepTime write SetThreadSleepTime; property UsagePageParam: TUsage read FUsagePageParam write SetUsagePageParam; property UsageParam: TUsage read FUsageParam write FUsageParam; // indexed properties property DeviceStrings[Idx: Byte]: string read GetDeviceStringAnsi; property DeviceStringsUnicode[Idx: Byte]: WideString read GetDeviceStringUnicode; property LinkCollectionNodes[Idx: WORD]: THIDPLinkCollectionNode read GetLinkCollectionNode; // event properties property OnData: TJvHidDataEvent read FData write SetDataEvent; property OnDataError: TJvHidDataErrorEvent read FDataError write FDataError; property OnUnplug: TJvHidUnplugEvent read FUnplug write FUnplug; end; // controller class to manage all HID devices {$IFDEF RTL230_UP} [ComponentPlatformsAttribute(pidWin32 or pidWin64)] {$ENDIF RTL230_UP} TJvHidDeviceController = class(TJvComponent) private // internal properties part FHidGuid: TGUID; FArrivalEvent: TJvHidPlugEvent; FDeviceChangeEvent: TNotifyEvent; FEnumerateEvent: TJvHidEnumerateEvent; FDevDataEvent: TJvHidDataEvent; FDevDataErrorEvent: TJvHidDataErrorEvent; FDevUnplugEvent: TJvHidUnplugEvent; FRemovalEvent: TJvHidUnplugEvent; FDevThreadSleepTime: Integer; FVersion: string; FDummy: string; // internal list of all HID device objects FList: TList; // counters for the list FNumCheckedInDevices: Integer; FNumCheckedOutDevices: Integer; FNumUnpluggedDevices: Integer; // reentrancy FInDeviceChange: Boolean; FLParam: LPARAM; // window to catch WM_DEVICECHANGE FHWnd: HWND; // internal worker functions function CheckThisOut(var HidDev: TJvHidDevice; Idx: Integer; Check: Boolean): Boolean; procedure EventPipe(var Msg: TMessage); // internal event implementors procedure SetDeviceChangeEvent(const Notifier: TNotifyEvent); procedure SetEnumerate(const Enumerator: TJvHidEnumerateEvent); procedure SetDevThreadSleepTime(const DevTime: Integer); procedure SetDevData(const DataEvent: TJvHidDataEvent); procedure SetDevDataError(const DataErrorEvent: TJvHidDataErrorEvent); procedure SetDevUnplug(const Unplugger: TJvHidUnplugEvent); protected procedure DoArrival(HidDev: TJvHidDevice); procedure DoRemoval(HidDev: TJvHidDevice); procedure DoDeviceChange; function DoEnumerate(HidDev: TJvHidDevice; Idx: Integer): Boolean; public // 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; const ClassName: string): Boolean; function CheckOutByID(var HidDev: TJvHidDevice; const Vid, Pid: Integer): Boolean; function CheckOutByIndex(var HidDev: TJvHidDevice; const Idx: Integer): Boolean; function CheckOutByProductName(var HidDev: TJvHidDevice; const ProductName: WideString): Boolean; function CheckOutByVendorName(var HidDev: TJvHidDevice; const VendorName: WideString): Boolean; function CheckOutByCallback(var HidDev: TJvHidDevice; Check: TJvHidCheckCallback): Boolean; // methods to count HID device objects function CountByClass(const ClassName: string): Integer; function CountByID(const Vid, Pid: Integer): Integer; function CountByProductName(const ProductName: WideString): Integer; function CountByVendorName(const VendorName: WideString): Integer; function CountByCallback(Check: TJvHidCheckCallback): Integer; // iterate over the HID devices function Enumerate: Integer; class function HidVersion: string; // 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; published property DevThreadSleepTime: Integer read FDevThreadSleepTime write SetDevThreadSleepTime default 100; property Version: string read FVersion write FDummy stored False; property OnArrival: TJvHidPlugEvent read FArrivalEvent write FArrivalEvent; // the iterator event property OnEnumerate: TJvHidEnumerateEvent read FEnumerateEvent write SetEnumerate; // the central event for HID device changes property OnDeviceChange: TNotifyEvent read FDeviceChangeEvent write SetDeviceChangeEvent; // these events are copied to TJvHidDevices on creation property OnDeviceData: TJvHidDataEvent read FDevDataEvent write SetDevData; property OnDeviceDataError: TJvHidDataErrorEvent read FDevDataErrorEvent write SetDevDataError; property OnDeviceUnplug: TJvHidUnplugEvent read FDevUnplugEvent write SetDevUnplug; property OnRemoval: TJvHidUnplugEvent read FRemovalEvent write FRemovalEvent; // to be callable at design time procedure DeviceChange; 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; function HidErrorString(const RetVal: NTSTATUS): string; // to register the component in the palette procedure Register; {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_45/run/JvHidControllerClass.pas $'; Revision: '$Revision: 13102 $'; Date: '$Date: 2011-09-07 07:46:34 +0200 (mer., 07 sept. 2011) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} implementation
09-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值