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;
18 DllInitialize(ULONG Unknown
)
33 IN PDRIVER_OBJECT DriverObject
,
34 IN PDEVICE_OBJECT PhysicalDeviceObject
)
36 WCHAR CharDeviceName
[64];
38 UNICODE_STRING DeviceName
;
39 PDEVICE_OBJECT NewDeviceObject
;
40 PHIDCLASS_FDO_EXTENSION FDODeviceExtension
;
41 ULONG DeviceExtensionSize
;
42 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
= (PHIDCLASS_DRIVER_EXTENSION
) 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
= (PHIDCLASS_FDO_EXTENSION
)NewDeviceObject
->DeviceExtension
;
78 /* zero device extension */
79 RtlZeroMemory(FDODeviceExtension
, sizeof(HIDCLASS_FDO_EXTENSION
));
81 /* initialize device extension */
82 FDODeviceExtension
->Common
.HidDeviceExtension
.PhysicalDeviceObject
= PhysicalDeviceObject
;
83 FDODeviceExtension
->Common
.HidDeviceExtension
.MiniDeviceExtension
= (PVOID
)((ULONG_PTR
)FDODeviceExtension
+ sizeof(HIDCLASS_FDO_EXTENSION
));
84 FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
= IoAttachDeviceToDeviceStack(NewDeviceObject
, PhysicalDeviceObject
);
85 FDODeviceExtension
->Common
.IsFDO
= TRUE
;
86 FDODeviceExtension
->Common
.DriverExtension
= DriverExtension
;
89 ASSERT(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
91 /* increment stack size */
92 NewDeviceObject
->StackSize
++;
94 /* init device object */
95 NewDeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
96 NewDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
98 /* now call driver provided add device routine */
99 ASSERT(DriverExtension
->AddDevice
!= 0);
100 Status
= DriverExtension
->AddDevice(DriverObject
, NewDeviceObject
);
101 if (!NT_SUCCESS(Status
))
104 DPRINT1("HIDCLASS: AddDevice failed with %x\n", Status
);
105 IoDetachDevice(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
106 IoDeleteDevice(NewDeviceObject
);
116 HidClassDriverUnload(
117 IN PDRIVER_OBJECT DriverObject
)
126 IN PDEVICE_OBJECT DeviceObject
,
129 PIO_STACK_LOCATION IoStack
;
130 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
131 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
132 PHIDCLASS_FILEOP_CONTEXT Context
;
135 // get device extension
137 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
138 if (CommonDeviceExtension
->IsFDO
)
141 // only supported for PDO
143 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
144 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
145 return STATUS_UNSUCCESSFUL
;
151 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
154 // get device extension
156 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)CommonDeviceExtension
;
159 // get stack location
161 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
163 DPRINT1("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
164 DPRINT1("Options %x\n", IoStack
->Parameters
.Create
.Options
);
165 DPRINT1("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
170 Context
= (PHIDCLASS_FILEOP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
176 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
177 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
178 return STATUS_INSUFFICIENT_RESOURCES
;
184 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
185 Context
->DeviceExtension
= PDODeviceExtension
;
186 KeInitializeSpinLock(&Context
->Lock
);
187 InitializeListHead(&Context
->ReadPendingIrpListHead
);
188 InitializeListHead(&Context
->IrpCompletedListHead
);
193 ASSERT(IoStack
->FileObject
);
194 IoStack
->FileObject
->FsContext
= (PVOID
)Context
;
199 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
200 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
201 return STATUS_SUCCESS
;
207 IN PDEVICE_OBJECT DeviceObject
,
210 PIO_STACK_LOCATION IoStack
;
211 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
212 PHIDCLASS_IRP_CONTEXT IrpContext
;
215 // get device extension
217 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
220 // is it a FDO request
222 if (CommonDeviceExtension
->IsFDO
)
225 // how did the request get there
227 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
228 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
229 return STATUS_INVALID_PARAMETER_1
;
233 // get stack location
235 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
240 ASSERT(IoStack
->FileObject
);
241 ASSERT(IoStack
->FileObject
->FsContext
);
246 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)IoStack
->FileObject
->FsContext
;
249 // cancel pending irps
256 IoStack
->FileObject
->FsContext
= NULL
;
261 ExFreePool(IrpContext
);
266 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
267 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
268 return STATUS_SUCCESS
;
272 HidClass_GetSystemAddress(
280 if (ReportMDL
->MdlFlags
& (MDL_SOURCE_IS_NONPAGED_POOL
| MDL_MAPPED_TO_SYSTEM_VA
))
283 // buffer is non paged pool
285 return ReportMDL
->MappedSystemVa
;
292 return MmMapLockedPages(ReportMDL
, KernelMode
);
298 HidClass_ReadCompleteIrp(
299 IN PDEVICE_OBJECT DeviceObject
,
303 PHIDCLASS_IRP_CONTEXT IrpContext
;
307 PHIDP_COLLECTION_DESC CollectionDescription
;
308 PHIDP_REPORT_IDS ReportDescription
;
313 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)Ctx
;
315 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
316 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
317 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
318 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
319 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
320 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
321 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
326 if (Irp
->IoStatus
.Information
)
331 Address
= (PUCHAR
)HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
335 // reports may have a report id prepended
340 // get collection description
342 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
343 ASSERT(CollectionDescription
);
346 // get report description
348 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
349 ASSERT(ReportDescription
);
351 if (CollectionDescription
&& ReportDescription
)
356 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
357 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
363 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
368 // copy result status
370 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
371 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
374 // free input report buffer
376 ExFreePool(IrpContext
->InputReportBuffer
);
379 // remove us from pending list
381 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
384 // remove from pending list
386 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
389 // insert into completed list
391 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
396 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
399 // complete original request
401 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
406 ExFreePool(IrpContext
);
411 return STATUS_MORE_PROCESSING_REQUIRED
;
416 IN PHIDCLASS_FILEOP_CONTEXT Context
)
420 PLIST_ENTRY ListEntry
;
425 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
430 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
435 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
440 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
446 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
456 IN PDEVICE_OBJECT DeviceObject
,
458 IN PHIDCLASS_FILEOP_CONTEXT Context
,
459 IN ULONG DeviceIoControlCode
,
460 IN ULONG BufferLength
,
462 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
465 PIO_STACK_LOCATION IoStack
;
466 PHIDCLASS_IRP_CONTEXT IrpContext
;
467 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
468 PHIDP_COLLECTION_DESC CollectionDescription
;
469 PHIDP_REPORT_IDS ReportDescription
;
472 // get an irp from fresh list
474 Irp
= HidClass_GetIrp(Context
);
480 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
486 return STATUS_INSUFFICIENT_RESOURCES
;
494 IoReuseIrp(Irp
, STATUS_SUCCESS
);
498 // allocate completion context
500 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
507 return STATUS_INSUFFICIENT_RESOURCES
;
511 // get device extension
513 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
514 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
519 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
520 IrpContext
->OriginalIrp
= RequestIrp
;
521 IrpContext
->FileOp
= Context
;
524 // get collection description
526 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
527 ASSERT(CollectionDescription
);
530 // get report description
532 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
533 ASSERT(ReportDescription
);
538 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
541 // store report length
543 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
548 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
549 if (!IrpContext
->InputReportBuffer
)
555 ExFreePool(IrpContext
);
556 return STATUS_INSUFFICIENT_RESOURCES
;
560 // get stack location
562 IoStack
= IoGetNextIrpStackLocation(Irp
);
565 // init stack location
567 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
568 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
569 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
570 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
571 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
572 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
573 IoStack
->DeviceObject
= DeviceObject
;
579 *OutIrpContext
= IrpContext
;
584 return STATUS_SUCCESS
;
591 IN PDEVICE_OBJECT DeviceObject
,
594 PIO_STACK_LOCATION IoStack
;
595 PHIDCLASS_FILEOP_CONTEXT Context
;
599 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
600 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
603 // get current stack location
605 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
608 // get device extension
610 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
611 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
616 ASSERT(IoStack
->FileObject
);
617 ASSERT(IoStack
->FileObject
->FsContext
);
622 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
626 // FIXME support polled devices
628 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
633 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
634 if (!NT_SUCCESS(Status
))
639 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
640 Irp
->IoStatus
.Status
= Status
;
641 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
648 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
651 // insert irp into pending list
653 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
656 // set completion routine
658 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
661 // make next location current
663 IoSetNextIrpStackLocation(NewIrp
);
668 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
673 IoMarkIrpPending(Irp
);
676 // lets dispatch the request
678 ASSERT(Context
->DeviceExtension
);
679 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
684 return STATUS_PENDING
;
690 IN PDEVICE_OBJECT DeviceObject
,
695 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
696 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
697 return STATUS_NOT_IMPLEMENTED
;
702 HidClass_DeviceControl(
703 IN PDEVICE_OBJECT DeviceObject
,
706 PIO_STACK_LOCATION IoStack
;
707 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
708 PHID_COLLECTION_INFORMATION CollectionInformation
;
709 PHIDP_COLLECTION_DESC CollectionDescription
;
710 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
713 // get device extension
715 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
716 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
719 // get pdo device extension
721 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
724 // get stack location
726 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
728 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
730 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
733 // check if output buffer is big enough
735 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
738 // invalid buffer size
740 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
741 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
742 return STATUS_INVALID_BUFFER_SIZE
;
748 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
749 ASSERT(CollectionInformation
);
752 // get collection description
754 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
755 ASSERT(CollectionDescription
);
758 // init result buffer
760 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
761 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
762 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
763 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
764 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
769 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
770 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
771 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
772 return STATUS_SUCCESS
;
774 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
777 // get collection description
779 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
780 ASSERT(CollectionDescription
);
783 // check if output buffer is big enough
785 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
788 // invalid buffer size
790 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
791 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
792 return STATUS_INVALID_BUFFER_SIZE
;
798 ASSERT(Irp
->UserBuffer
);
799 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
804 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
805 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
806 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
807 return STATUS_SUCCESS
;
811 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
812 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
813 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
814 return STATUS_NOT_IMPLEMENTED
;
821 HidClass_InternalDeviceControl(
822 IN PDEVICE_OBJECT DeviceObject
,
827 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
828 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
829 return STATUS_NOT_IMPLEMENTED
;
836 IN PDEVICE_OBJECT DeviceObject
,
841 return STATUS_NOT_IMPLEMENTED
;
847 IN PDEVICE_OBJECT DeviceObject
,
850 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
853 // get common device extension
855 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
858 // check type of device object
860 if (CommonDeviceExtension
->IsFDO
)
865 return HidClassFDO_PnP(DeviceObject
, Irp
);
872 return HidClassPDO_PnP(DeviceObject
, Irp
);
878 HidClass_DispatchDefault(
879 IN PDEVICE_OBJECT DeviceObject
,
882 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
885 // get common device extension
887 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
890 // FIXME: support PDO
892 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
895 // skip current irp stack location
897 IoSkipCurrentIrpStackLocation(Irp
);
900 // dispatch to lower device object
902 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
909 IN PDEVICE_OBJECT DeviceObject
,
912 PIO_STACK_LOCATION IoStack
;
915 // get current stack location
917 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
918 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
921 // dispatch request based on major function
923 switch(IoStack
->MajorFunction
)
926 return HidClass_Create(DeviceObject
, Irp
);
928 return HidClass_Close(DeviceObject
, Irp
);
930 return HidClass_Read(DeviceObject
, Irp
);
932 return HidClass_Write(DeviceObject
, Irp
);
933 case IRP_MJ_DEVICE_CONTROL
:
934 return HidClass_DeviceControl(DeviceObject
, Irp
);
935 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
936 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
938 return HidClass_Power(DeviceObject
, Irp
);
940 return HidClass_PnP(DeviceObject
, Irp
);
942 return HidClass_DispatchDefault(DeviceObject
, Irp
);
948 HidRegisterMinidriver(
949 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
952 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
954 /* check if the version matches */
955 if (MinidriverRegistration
->Revision
> HID_REVISION
)
957 /* revision mismatch */
959 return STATUS_REVISION_MISMATCH
;
962 /* now allocate the driver object extension */
963 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
964 if (!NT_SUCCESS(Status
))
966 /* failed to allocate driver extension */
971 /* zero driver extension */
972 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
974 /* init driver extension */
975 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
976 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
977 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
978 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
979 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
981 /* copy driver dispatch routines */
982 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
984 /* initialize lock */
985 KeInitializeSpinLock(&DriverExtension
->Lock
);
987 /* now replace dispatch routines */
988 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
989 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
990 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
991 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
992 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
993 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
994 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
995 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
996 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
997 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1000 return STATUS_SUCCESS
;