https://git.reactos.org/?p=reactos.git;a=commitdiff;h=501116b68f1da4e380f5630672b0fe099f22ab55

commit 501116b68f1da4e380f5630672b0fe099f22ab55
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Fri Apr 19 22:40:32 2019 +0200
Commit:     Hervé Poussineau <[email protected]>
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_ */

Reply via email to