2 * PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/hid/hidclass/hidclass.c
5 * PURPOSE: HID Class Driver
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
13 static LPWSTR ClientIdentificationAddress
= L
"HIDCLASS";
14 static ULONG HidClassDeviceNumber
= 0;
19 IN PUNICODE_STRING RegistryPath
)
21 return STATUS_SUCCESS
;
28 return STATUS_SUCCESS
;
34 IN PDRIVER_OBJECT DriverObject
,
35 IN PDEVICE_OBJECT PhysicalDeviceObject
)
37 WCHAR CharDeviceName
[64];
39 UNICODE_STRING DeviceName
;
40 PDEVICE_OBJECT NewDeviceObject
;
41 PHIDCLASS_FDO_EXTENSION FDODeviceExtension
;
42 ULONG DeviceExtensionSize
;
43 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
45 /* increment device number */
46 InterlockedIncrement((PLONG
)&HidClassDeviceNumber
);
48 /* construct device name */
49 swprintf(CharDeviceName
, L
"\\Device\\_HID%08x", HidClassDeviceNumber
);
51 /* initialize device name */
52 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
54 /* get driver object extension */
55 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, ClientIdentificationAddress
);
60 return STATUS_DEVICE_CONFIGURATION_ERROR
;
63 /* calculate device extension size */
64 DeviceExtensionSize
= sizeof(HIDCLASS_FDO_EXTENSION
) + DriverExtension
->DeviceExtensionSize
;
66 /* now create the device */
67 Status
= IoCreateDevice(DriverObject
, DeviceExtensionSize
, &DeviceName
, FILE_DEVICE_UNKNOWN
, 0, FALSE
, &NewDeviceObject
);
68 if (!NT_SUCCESS(Status
))
70 /* failed to create device object */
75 /* get device extension */
76 FDODeviceExtension
= NewDeviceObject
->DeviceExtension
;
78 /* zero device extension */
79 RtlZeroMemory(FDODeviceExtension
, sizeof(HIDCLASS_FDO_EXTENSION
));
81 /* initialize device extension */
82 FDODeviceExtension
->Common
.IsFDO
= TRUE
;
83 FDODeviceExtension
->Common
.DriverExtension
= DriverExtension
;
84 FDODeviceExtension
->Common
.HidDeviceExtension
.PhysicalDeviceObject
= PhysicalDeviceObject
;
85 FDODeviceExtension
->Common
.HidDeviceExtension
.MiniDeviceExtension
= (PVOID
)((ULONG_PTR
)FDODeviceExtension
+ sizeof(HIDCLASS_FDO_EXTENSION
));
86 FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
= IoAttachDeviceToDeviceStack(NewDeviceObject
, PhysicalDeviceObject
);
87 if (FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
== NULL
)
90 IoDeleteDevice(NewDeviceObject
);
91 DPRINT1("[HIDCLASS] failed to attach to device stack\n");
92 return STATUS_DEVICE_REMOVED
;
96 ASSERT(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
98 /* increment stack size */
99 NewDeviceObject
->StackSize
++;
101 /* init device object */
102 NewDeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
103 NewDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
105 /* now call driver provided add device routine */
106 ASSERT(DriverExtension
->AddDevice
!= 0);
107 Status
= DriverExtension
->AddDevice(DriverObject
, NewDeviceObject
);
108 if (!NT_SUCCESS(Status
))
111 DPRINT1("HIDCLASS: AddDevice failed with %x\n", Status
);
112 IoDetachDevice(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
113 IoDeleteDevice(NewDeviceObject
);
123 HidClassDriverUnload(
124 IN PDRIVER_OBJECT DriverObject
)
132 IN PDEVICE_OBJECT DeviceObject
,
135 PIO_STACK_LOCATION IoStack
;
136 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
137 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
138 PHIDCLASS_FILEOP_CONTEXT Context
;
141 // get device extension
143 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
144 if (CommonDeviceExtension
->IsFDO
)
149 // only supported for PDO
151 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
152 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
153 return STATUS_UNSUCCESSFUL
;
156 // ReactOS PnP manager [...]
158 DPRINT1("[HIDCLASS] PnP HACK\n");
159 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
160 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
161 return STATUS_SUCCESS
;
168 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
171 // get device extension
173 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
176 // get stack location
178 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
180 DPRINT("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
181 DPRINT("Options %x\n", IoStack
->Parameters
.Create
.Options
);
182 DPRINT("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
187 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
), HIDCLASS_TAG
);
193 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
194 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
195 return STATUS_INSUFFICIENT_RESOURCES
;
201 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
202 Context
->DeviceExtension
= PDODeviceExtension
;
203 KeInitializeSpinLock(&Context
->Lock
);
204 InitializeListHead(&Context
->ReadPendingIrpListHead
);
205 InitializeListHead(&Context
->IrpCompletedListHead
);
206 KeInitializeEvent(&Context
->IrpReadComplete
, NotificationEvent
, FALSE
);
211 ASSERT(IoStack
->FileObject
);
212 IoStack
->FileObject
->FsContext
= Context
;
217 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
218 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
219 return STATUS_SUCCESS
;
225 IN PDEVICE_OBJECT DeviceObject
,
228 PIO_STACK_LOCATION IoStack
;
229 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
230 PHIDCLASS_FILEOP_CONTEXT IrpContext
;
231 BOOLEAN IsRequestPending
= FALSE
;
237 // get device extension
239 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
242 // is it a FDO request
244 if (CommonDeviceExtension
->IsFDO
)
247 // how did the request get there
249 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
250 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
251 return STATUS_INVALID_PARAMETER_1
;
255 // get stack location
257 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
262 ASSERT(IoStack
->FileObject
);
263 ASSERT(IoStack
->FileObject
->FsContext
);
268 IrpContext
= IoStack
->FileObject
->FsContext
;
274 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
276 if (!IsListEmpty(&IrpContext
->ReadPendingIrpListHead
))
281 IsRequestPending
= TRUE
;
287 IrpContext
->StopInProgress
= TRUE
;
292 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
294 if (IsRequestPending
)
297 // wait for request to complete
299 DPRINT1("[HIDCLASS] Waiting for read irp completion...\n");
300 KeWaitForSingleObject(&IrpContext
->IrpReadComplete
, Executive
, KernelMode
, FALSE
, NULL
);
306 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
311 ASSERT(IsListEmpty(&IrpContext
->ReadPendingIrpListHead
));
316 while (!IsListEmpty(&IrpContext
->IrpCompletedListHead
))
321 Entry
= RemoveHeadList(&IrpContext
->IrpCompletedListHead
);
326 ListIrp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
337 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
342 IoStack
->FileObject
->FsContext
= NULL
;
347 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
352 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
353 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
354 return STATUS_SUCCESS
;
359 HidClass_ReadCompleteIrp(
360 IN PDEVICE_OBJECT DeviceObject
,
364 PHIDCLASS_IRP_CONTEXT IrpContext
;
368 PHIDP_COLLECTION_DESC CollectionDescription
;
369 PHIDP_REPORT_IDS ReportDescription
;
377 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
378 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
379 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
380 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
381 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
382 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
383 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
388 if (Irp
->IoStatus
.Information
)
393 Address
= MmGetSystemAddressForMdlSafe(IrpContext
->OriginalIrp
->MdlAddress
, NormalPagePriority
);
397 // reports may have a report id prepended
402 // get collection description
404 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
405 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
406 ASSERT(CollectionDescription
);
409 // get report description
411 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
412 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
413 ASSERT(ReportDescription
);
415 if (CollectionDescription
&& ReportDescription
)
420 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
421 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
427 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
432 // copy result status
434 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
435 IrpContext
->OriginalIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
438 // free input report buffer
440 ExFreePoolWithTag(IrpContext
->InputReportBuffer
, HIDCLASS_TAG
);
443 // remove us from pending list
445 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
448 // remove from pending list
450 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
455 IsEmpty
= IsListEmpty(&IrpContext
->FileOp
->ReadPendingIrpListHead
);
458 // insert into completed list
460 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
465 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
468 // complete original request
470 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
473 DPRINT("StopInProgress %x IsEmpty %x\n", IrpContext
->FileOp
->StopInProgress
, IsEmpty
);
474 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
479 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
480 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
483 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
488 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
489 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
495 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
500 return STATUS_MORE_PROCESSING_REQUIRED
;
505 IN PHIDCLASS_FILEOP_CONTEXT Context
)
509 PLIST_ENTRY ListEntry
;
514 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
519 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
524 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
529 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
535 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
545 IN PDEVICE_OBJECT DeviceObject
,
547 IN PHIDCLASS_FILEOP_CONTEXT Context
,
548 IN ULONG DeviceIoControlCode
,
549 IN ULONG BufferLength
,
551 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
554 PIO_STACK_LOCATION IoStack
;
555 PHIDCLASS_IRP_CONTEXT IrpContext
;
556 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
557 PHIDP_COLLECTION_DESC CollectionDescription
;
558 PHIDP_REPORT_IDS ReportDescription
;
561 // get an irp from fresh list
563 Irp
= HidClass_GetIrp(Context
);
569 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
575 return STATUS_INSUFFICIENT_RESOURCES
;
583 IoReuseIrp(Irp
, STATUS_SUCCESS
);
587 // allocate completion context
589 IrpContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
), HIDCLASS_TAG
);
596 return STATUS_INSUFFICIENT_RESOURCES
;
600 // get device extension
602 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
603 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
608 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
609 IrpContext
->OriginalIrp
= RequestIrp
;
610 IrpContext
->FileOp
= Context
;
613 // get collection description
615 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
616 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
617 ASSERT(CollectionDescription
);
620 // get report description
622 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
623 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
624 ASSERT(ReportDescription
);
629 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
631 if (Context
->StopInProgress
)
636 DPRINT1("[HIDCLASS] Stop In Progress\n");
637 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
638 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
639 return STATUS_CANCELLED
;
644 // store report length
646 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
651 IrpContext
->InputReportBuffer
= ExAllocatePoolWithTag(NonPagedPool
, IrpContext
->InputReportBufferLength
, HIDCLASS_TAG
);
652 if (!IrpContext
->InputReportBuffer
)
658 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
659 return STATUS_INSUFFICIENT_RESOURCES
;
663 // get stack location
665 IoStack
= IoGetNextIrpStackLocation(Irp
);
668 // init stack location
670 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
671 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
672 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
673 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
674 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
675 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
676 IoStack
->DeviceObject
= DeviceObject
;
682 *OutIrpContext
= IrpContext
;
687 return STATUS_SUCCESS
;
693 IN PDEVICE_OBJECT DeviceObject
,
696 PIO_STACK_LOCATION IoStack
;
697 PHIDCLASS_FILEOP_CONTEXT Context
;
701 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
702 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
705 // get current stack location
707 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
710 // get device extension
712 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
713 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
718 ASSERT(IoStack
->FileObject
);
719 ASSERT(IoStack
->FileObject
->FsContext
);
724 Context
= IoStack
->FileObject
->FsContext
;
728 // FIXME support polled devices
730 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
732 if (Context
->StopInProgress
)
737 DPRINT1("[HIDCLASS] Stop In Progress\n");
738 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
739 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
740 return STATUS_CANCELLED
;
746 Status
= HidClass_BuildIrp(DeviceObject
,
749 IOCTL_HID_READ_REPORT
,
750 IoStack
->Parameters
.Read
.Length
,
753 if (!NT_SUCCESS(Status
))
758 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
759 Irp
->IoStatus
.Status
= Status
;
760 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
767 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
770 // insert irp into pending list
772 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
775 // set completion routine
777 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
780 // make next location current
782 IoSetNextIrpStackLocation(NewIrp
);
787 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
792 IoMarkIrpPending(Irp
);
795 // let's dispatch the request
797 ASSERT(Context
->DeviceExtension
);
798 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
803 return STATUS_PENDING
;
809 IN PDEVICE_OBJECT DeviceObject
,
814 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
815 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
816 return STATUS_NOT_IMPLEMENTED
;
821 HidClass_DeviceControl(
822 IN PDEVICE_OBJECT DeviceObject
,
825 PIO_STACK_LOCATION IoStack
;
826 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
827 PHID_COLLECTION_INFORMATION CollectionInformation
;
828 PHIDP_COLLECTION_DESC CollectionDescription
;
829 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
832 // get device extension
834 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
837 // only PDO are supported
839 if (CommonDeviceExtension
->IsFDO
)
844 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
845 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
846 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
847 return STATUS_INVALID_PARAMETER_1
;
850 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
853 // get pdo device extension
855 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
858 // get stack location
860 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
862 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
864 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
867 // check if output buffer is big enough
869 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
872 // invalid buffer size
874 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
875 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
876 return STATUS_INVALID_BUFFER_SIZE
;
882 CollectionInformation
= Irp
->AssociatedIrp
.SystemBuffer
;
883 ASSERT(CollectionInformation
);
886 // get collection description
888 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
889 PDODeviceExtension
->CollectionNumber
);
890 ASSERT(CollectionDescription
);
893 // init result buffer
895 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
896 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
897 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
898 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
899 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
904 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
905 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
906 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
907 return STATUS_SUCCESS
;
909 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
912 // get collection description
914 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
915 PDODeviceExtension
->CollectionNumber
);
916 ASSERT(CollectionDescription
);
919 // check if output buffer is big enough
921 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
924 // invalid buffer size
926 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
927 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
928 return STATUS_INVALID_BUFFER_SIZE
;
934 ASSERT(Irp
->UserBuffer
);
935 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
940 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
941 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
942 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
943 return STATUS_SUCCESS
;
947 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
948 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
949 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
950 return STATUS_NOT_IMPLEMENTED
;
957 HidClass_InternalDeviceControl(
958 IN PDEVICE_OBJECT DeviceObject
,
963 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
964 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
965 return STATUS_NOT_IMPLEMENTED
;
971 IN PDEVICE_OBJECT DeviceObject
,
974 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
975 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
977 if (CommonDeviceExtension
->IsFDO
)
979 IoCopyCurrentIrpStackLocationToNext(Irp
);
980 return HidClassFDO_DispatchRequest(DeviceObject
, Irp
);
984 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
985 PoStartNextPowerIrp(Irp
);
986 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
987 return STATUS_SUCCESS
;
994 IN PDEVICE_OBJECT DeviceObject
,
997 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1000 // get common device extension
1002 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
1005 // check type of device object
1007 if (CommonDeviceExtension
->IsFDO
)
1012 return HidClassFDO_PnP(DeviceObject
, Irp
);
1019 return HidClassPDO_PnP(DeviceObject
, Irp
);
1025 HidClass_DispatchDefault(
1026 IN PDEVICE_OBJECT DeviceObject
,
1029 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1032 // get common device extension
1034 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
1037 // FIXME: support PDO
1039 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
1042 // skip current irp stack location
1044 IoSkipCurrentIrpStackLocation(Irp
);
1047 // dispatch to lower device object
1049 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
1055 IN PDEVICE_OBJECT DeviceObject
,
1058 PIO_STACK_LOCATION IoStack
;
1061 // get current stack location
1063 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1064 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
1067 // dispatch request based on major function
1069 switch (IoStack
->MajorFunction
)
1072 return HidClass_Create(DeviceObject
, Irp
);
1074 return HidClass_Close(DeviceObject
, Irp
);
1076 return HidClass_Read(DeviceObject
, Irp
);
1078 return HidClass_Write(DeviceObject
, Irp
);
1079 case IRP_MJ_DEVICE_CONTROL
:
1080 return HidClass_DeviceControl(DeviceObject
, Irp
);
1081 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1082 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
1084 return HidClass_Power(DeviceObject
, Irp
);
1086 return HidClass_PnP(DeviceObject
, Irp
);
1088 return HidClass_DispatchDefault(DeviceObject
, Irp
);
1094 HidRegisterMinidriver(
1095 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
1098 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
1100 /* check if the version matches */
1101 if (MinidriverRegistration
->Revision
> HID_REVISION
)
1103 /* revision mismatch */
1105 return STATUS_REVISION_MISMATCH
;
1108 /* now allocate the driver object extension */
1109 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
,
1110 ClientIdentificationAddress
,
1111 sizeof(HIDCLASS_DRIVER_EXTENSION
),
1112 (PVOID
*)&DriverExtension
);
1113 if (!NT_SUCCESS(Status
))
1115 /* failed to allocate driver extension */
1120 /* zero driver extension */
1121 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
1123 /* init driver extension */
1124 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1125 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1126 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1127 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1128 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1130 /* copy driver dispatch routines */
1131 RtlCopyMemory(DriverExtension
->MajorFunction
,
1132 MinidriverRegistration
->DriverObject
->MajorFunction
,
1133 sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+ 1));
1135 /* initialize lock */
1136 KeInitializeSpinLock(&DriverExtension
->Lock
);
1138 /* now replace dispatch routines */
1139 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1140 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1141 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1142 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1143 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1144 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1145 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1146 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1147 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1148 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1151 return STATUS_SUCCESS
;