https://git.reactos.org/?p=reactos.git;a=commitdiff;h=501116b68f1da4e380f563...
commit 501116b68f1da4e380f5630672b0fe099f22ab55 Author: Hervé Poussineau hpoussin@reactos.org AuthorDate: Fri Apr 19 22:40:32 2019 +0200 Commit: Hervé Poussineau hpoussin@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_ */