📄 hidcontrollerclass.pas
字号:
}
destructor TJvHidDevice.Destroy;
var
i: Integer;
begin
// free the data which needs special handling
CloseFile;
HidD_FreePreparsedData(FPreparsedData);
FDeviceStrings.Free;
FLanguageStrings.Free;
FLinkCollectionNodes.Free;
FreeMem(FLinkCollection);
// if controller exists
if FMyController <> nil then
with FMyController do
begin
// delete device from controller list
for i := 0 to FList.Count-1 do
if FList.Items[i] = Self then
begin
// if device is plugged in create a checked in copy
if IsPluggedIn then
begin
FList.Items[i] := TJvHidDevice.Create(DevicePath, FDevRegKey, FMyController.OnDeviceUnplug);
TJvHidDevice(FList.Items[i]).FMyController := FMyController;
end
else
FList.Delete(i);
Break;
end;
end;
inherited Destroy;
end;
// if check changes change check only here
function TJvHidDevice.IsAccessible: Boolean;
begin
Result := IsPluggedIn and (IsCheckedOut or FIsEnumerated);
end;
// open the device "file" (for the other methods)
function TJvHidDevice.OpenFile: Boolean;
begin
// check if open allowed (propagates this state)
if IsAccessible then
if HidFileHandle = INVALID_HANDLE_VALUE then // if not already opened
begin
FNumInputBuffers := 0;
FHidFileHandle := CreateFile(PChar(FDevicePath), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if HidFileHandle <> INVALID_HANDLE_VALUE then
HidD_GetNumInputBuffers(HidFileHandle, FNumInputBuffers);
end;
Result := HidFileHandle <> INVALID_HANDLE_VALUE;
end;
// implement OnUnplug event
procedure TJvHidDevice.DoUnplug;
begin
CloseFile;
FIsPluggedIn := False;
// event even for checked in devices
if Assigned(FUnplug) then
FUnplug(Self);
// guarantees that event is only called once
OnUnplug := nil;
end;
// assign the OnUnplug event
procedure TJvHidDevice.SetUnplug(const value: TJvHidUnplugEvent);
begin
if @value <> @FUnplug then
FUnplug := value;
end;
// implementing properties write
procedure TJvHidDevice.SetNumInputBuffers(const Num: Integer);
begin
if OpenFile then
if HidD_SetNumInputBuffers(HidFileHandle, Num) then
FNumInputBuffers := Num;
end;
procedure TJvHidDevice.SetReportTypeParam(const ReportType: THIDPReportType);
begin
FReportTypeParam := ReportType;
if IsAccessible then
begin
FMaxDataListLength := HidP_MaxDataListLength (ReportTypeParam, PreparsedData);
FMaxUsageListLength := HidP_MaxUsageListLength (ReportTypeParam, UsagePageParam, PreparsedData);
FMaxButtonListLength := HidP_MaxButtonListLength(ReportTypeParam, UsagePageParam, PreparsedData);
end;
end;
procedure TJvHidDevice.SetUsagePageParam (const UsagePage: TUsage);
begin
FUsagePageParam := UsagePage;
if IsAccessible then
begin
FMaxDataListLength := HidP_MaxDataListLength (ReportTypeParam, PreparsedData);
FMaxUsageListLength := HidP_MaxUsageListLength (ReportTypeParam, UsagePageParam, PreparsedData);
FMaxButtonListLength := HidP_MaxButtonListLength(ReportTypeParam, UsagePageParam, PreparsedData);
end;
end;
procedure TJvHidDevice.SetConfiguration(Config: THIDDConfiguration);
begin
if OpenFile then
if HidD_SetConfiguration(HidFileHandle, Config, Sizeof(THIDDConfiguration)) then
FConfiguration := Config;
end;
//-- TJvHidDevice methods -----------------------------------------------
{
* generally the parameter count of the methods is reduced with the Param propertiies
* first assign the Param properties the desired value then call a method
* normally you will address the same Usage, UsagePage, ReportType or LinkCollection
* with more than one method
*
* the methods will open the device file when needed
* this file is not closed until unplug or destruction to speed up access
}
// close the device "file"
// if you want to open the file directly close this to get access
procedure TJvHidDevice.CloseFile;
begin
if HidFileHandle <> INVALID_HANDLE_VALUE then
CloseHandle(HidFileHandle);
FNumInputBuffers := 0;
FHidFileHandle := INVALID_HANDLE_VALUE;
end;
function TJvHidDevice.FlushQueue: Boolean;
begin
Result := False;
if OpenFile then
Result := HidD_FlushQueue(HidFileHandle);
end;
function TJvHidDevice.GetFeature(var Report; const Size: Integer): Boolean;
begin
Result := False;
if OpenFile then
Result := HidD_GetFeature(HidFileHandle, Report, Size);
end;
function TJvHidDevice.SetFeature(var Report; const Size: Integer): Boolean;
begin
Result := False;
if OpenFile then
Result := HidD_SetFeature(HidFileHandle, Report, Size);
end;
function TJvHidDevice.GetPhysicalDescriptor(var Buffer; const Size: Integer): Boolean;
begin
Result := False;
if OpenFile then
Result := HidD_GetPhysicalDescriptor(HidFileHandle, Buffer, Size);
end;
function TJvHidDevice.GetSpecificButtonCaps(ButtonCaps: PHIDPButtonCaps; var Count: WORD): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetSpecificButtonCaps(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam, ButtonCaps, Count, PreparsedData);
end;
function TJvHidDevice.GetButtonCaps(ButtonCaps: PHIDPButtonCaps; var Count: WORD): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetButtonCaps(ReportTypeParam, ButtonCaps, Count, PreparsedData);
end;
function TJvHidDevice.GetSpecificValueCaps(ValueCaps: PHIDPValueCaps; var Count: WORD): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetSpecificValueCaps(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam, ValueCaps, Count, PreparsedData);
end;
function TJvHidDevice.GetValueCaps(ValueCaps: PHIDPValueCaps; var Count: WORD): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetValueCaps(ReportTypeParam, ValueCaps, Count, PreparsedData);
end;
function TJvHidDevice.GetData(DataList: PHIDPData; var DataLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetData(ReportTypeParam, DataList, DataLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetData(DataList: PHIDPData; var DataLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetData(ReportTypeParam, DataList, DataLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsages(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetButtons(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsagesEx(UsageList: PUsageAndPage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsagesEx(ReportTypeParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetButtonsEx(UsageList: PUsageAndPage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetButtonsEx(ReportTypeParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsages(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetButtons(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.UnsetUsages(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_UnsetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.UnsetButtons(UsageList: PUsage; var UsageLength: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_UnsetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsageValue(var UsageValue: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetScaledUsageValue(var UsageValue: Integer; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetScaledUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsageValueArray(UsageValue: PChar; UsageValueByteLength: WORD; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsageValueArray(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, UsageValueByteLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsageValue(UsageValue: ULong; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetScaledUsageValue(UsageValue: Integer; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetScaledUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsageValueArray(UsageValue: PChar; UsageValueByteLength: WORD; var Report; ReportLength: ULong): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsageValueArray(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, UsageValueByteLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.ReadFile(var Report; ToRead: DWORD; var BytesRead: DWORD): Boolean;
begin
Result := False;
if OpenFile then
Result := Windows.ReadFile(HidFileHandle, Report, ToRead, BytesRead, nil);
end;
function TJvHidDevice.WriteFile(var Report; ToWrite: DWORD; var BytesWritten: DWORD): Boolean;
begin
Result := False;
if OpenFile then
Result := Windows.WriteFile(HidFileHandle, Report, ToWrite, BytesWritten, nil);
end;
//== TJvHidDeviceController ===========================================
// internal worker function to find all Hid devices and create their objects
procedure TJvHidDeviceController.FillInList(var List: TList);
var
PnPHandle: HDEVINFO;
DevData: TSPDevInfoData;
DeviceInterfaceData: TSPDeviceInterfaceData;
FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
Success: LongBool;
devn: Integer;
BytesReturned: DWORD;
HidDev: TJvHidDevice;
begin
// create list
List := TList.Create;
// Get a handle for the Plug and Play node and request currently active HID devices
PnPHandle := SetupDiGetClassDevs(@FHidGuid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then
Exit;
devn := 0;
repeat
DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
// Is there a HID device at this table entry?
Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, FHidGuid, devn, DeviceInterfaceData);
if Success then
begin
DevData.cbSize := SizeOf(DevData);
BytesReturned := 0;
SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, @BytesReturned, @DevData);
if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
FunctionClassDeviceData := AllocMem(BytesReturned);
FunctionClassDeviceData.cbSize := 5;
if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, FunctionClassDeviceData, BytesReturned, @BytesReturned, @DevData) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -