https://git.reactos.org/?p=reactos.git;a=commitdiff;h=501116b68f1da4e380f56…
commit 501116b68f1da4e380f5630672b0fe099f22ab55
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Fri Apr 19 22:40:32 2019 +0200
Commit: Hervé Poussineau <hpoussin(a)reactos.org>
CommitDate: Fri Apr 19 22:46:03 2019 +0200
[HIDCLASS] Implement IOCTL_HID_GET_FEATURE/IOCTL_HID_SET_FEATURE
---
drivers/hid/hidclass/hidclass.c | 114 ++++++++++++++++++++++++++++++++++++++++
drivers/hid/hidclass/pdo.c | 26 +++++++++
drivers/hid/hidclass/precomp.h | 5 ++
3 files changed, 145 insertions(+)
diff --git a/drivers/hid/hidclass/hidclass.c b/drivers/hid/hidclass/hidclass.c
index 6d21f14b70..30d6f8d409 100644
--- a/drivers/hid/hidclass/hidclass.c
+++ b/drivers/hid/hidclass/hidclass.c
@@ -934,6 +934,120 @@ HidClass_DeviceControl(
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
+ case IOCTL_HID_GET_FEATURE:
+ {
+ PIRP SubIrp;
+ KEVENT Event;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HID_XFER_PACKET XferPacket;
+ NTSTATUS Status;
+ PHIDP_REPORT_IDS ReportDescription;
+
+ if (IoStack->Parameters.DeviceIoControl.InputBufferLength < 1)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+ }
+ ReportDescription =
HidClassPDO_GetReportDescriptionByReportID(&PDODeviceExtension->Common.DeviceDescription,
((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0]);
+ if (!ReportDescription ||
IoStack->Parameters.DeviceIoControl.OutputBufferLength <
ReportDescription->FeatureLength)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ RtlZeroMemory(&XferPacket, sizeof(XferPacket));
+ XferPacket.reportBufferLen = ReportDescription->FeatureLength;
+ XferPacket.reportBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,
NormalPagePriority);
+ XferPacket.reportId = ((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0];
+ if (!XferPacket.reportBuffer)
+ {
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ SubIrp = IoBuildDeviceIoControlRequest(
+ IOCTL_HID_GET_FEATURE,
+ CommonDeviceExtension->HidDeviceExtension.NextDeviceObject,
+ NULL, 0,
+ NULL, 0,
+ TRUE,
+ &Event,
+ &IoStatusBlock);
+ if (!SubIrp)
+ {
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+ SubIrp->UserBuffer = &XferPacket;
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ Status =
IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, SubIrp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatusBlock.Status;
+ }
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ case IOCTL_HID_SET_FEATURE:
+ {
+ PIRP SubIrp;
+ KEVENT Event;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HID_XFER_PACKET XferPacket;
+ NTSTATUS Status;
+ PHIDP_REPORT_IDS ReportDescription;
+
+ if (IoStack->Parameters.DeviceIoControl.InputBufferLength < 1)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+ }
+ ReportDescription =
HidClassPDO_GetReportDescriptionByReportID(&PDODeviceExtension->Common.DeviceDescription,
((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0]);
+ if (!ReportDescription ||
IoStack->Parameters.DeviceIoControl.InputBufferLength <
ReportDescription->FeatureLength)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ RtlZeroMemory(&XferPacket, sizeof(XferPacket));
+ XferPacket.reportBufferLen = ReportDescription->FeatureLength;
+ XferPacket.reportBuffer = Irp->AssociatedIrp.SystemBuffer;
+ XferPacket.reportId = XferPacket.reportBuffer[0];
+
+ SubIrp = IoBuildDeviceIoControlRequest(
+ IOCTL_HID_SET_FEATURE,
+ CommonDeviceExtension->HidDeviceExtension.NextDeviceObject,
+ NULL, 0,
+ NULL, 0,
+ TRUE,
+ &Event,
+ &IoStatusBlock);
+ if (!SubIrp)
+ {
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+ SubIrp->UserBuffer = &XferPacket;
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ Status =
IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, SubIrp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatusBlock.Status;
+ }
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
default:
{
DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not
implemented\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
diff --git a/drivers/hid/hidclass/pdo.c b/drivers/hid/hidclass/pdo.c
index 761cb24d92..f629ebd411 100644
--- a/drivers/hid/hidclass/pdo.c
+++ b/drivers/hid/hidclass/pdo.c
@@ -67,6 +67,32 @@ HidClassPDO_GetReportDescription(
return NULL;
}
+PHIDP_REPORT_IDS
+HidClassPDO_GetReportDescriptionByReportID(
+ PHIDP_DEVICE_DESC DeviceDescription,
+ UCHAR ReportID)
+{
+ ULONG Index;
+
+ for (Index = 0; Index < DeviceDescription->ReportIDsLength; Index++)
+ {
+ if (DeviceDescription->ReportIDs[Index].ReportID == ReportID)
+ {
+ //
+ // found report id
+ //
+ return &DeviceDescription->ReportIDs[Index];
+ }
+ }
+
+ //
+ // failed to find report id
+ //
+ DPRINT1("[HIDCLASS] GetReportDescriptionByReportID ReportID %x not
found\n", ReportID);
+ ASSERT(FALSE);
+ return NULL;
+}
+
NTSTATUS
HidClassPDO_HandleQueryDeviceId(
IN PDEVICE_OBJECT DeviceObject,
diff --git a/drivers/hid/hidclass/precomp.h b/drivers/hid/hidclass/precomp.h
index afaa571d7d..d3b0be8133 100644
--- a/drivers/hid/hidclass/precomp.h
+++ b/drivers/hid/hidclass/precomp.h
@@ -213,4 +213,9 @@ HidClassPDO_GetReportDescription(
PHIDP_DEVICE_DESC DeviceDescription,
ULONG CollectionNumber);
+PHIDP_REPORT_IDS
+HidClassPDO_GetReportDescriptionByReportID(
+ PHIDP_DEVICE_DESC DeviceDescription,
+ UCHAR ReportID);
+
#endif /* _HIDCLASS_PCH_ */