From: Hervé Poussineau Date: Fri, 19 Apr 2019 20:40:32 +0000 (+0200) Subject: [HIDCLASS] Implement IOCTL_HID_GET_FEATURE/IOCTL_HID_SET_FEATURE X-Git-Tag: 0.4.14-dev~1161 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=501116b68f1da4e380f5630672b0fe099f22ab55 [HIDCLASS] Implement IOCTL_HID_GET_FEATURE/IOCTL_HID_SET_FEATURE --- diff --git a/drivers/hid/hidclass/hidclass.c b/drivers/hid/hidclass/hidclass.c index 6d21f14b70c..30d6f8d4091 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 761cb24d928..f629ebd411f 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 afaa571d7d2..d3b0be81335 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_ */