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_DEVICE_DESC DeviceDescription
;
308 ULONG CollectionIndex
;
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
= HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
335 // reports may have a report id prepended
337 CollectionIndex
= IrpContext
->FileOp
->DeviceExtension
->CollectionIndex
;
338 DeviceDescription
= &IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
;
343 ASSERT(DeviceDescription
->CollectionDesc
[CollectionIndex
].InputLength
>= DeviceDescription
->ReportIDs
[CollectionIndex
].InputLength
);
344 Offset
= DeviceDescription
->CollectionDesc
[CollectionIndex
].InputLength
- DeviceDescription
->ReportIDs
[CollectionIndex
].InputLength
;
349 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
354 // copy result status
356 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
357 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
360 // free input report buffer
362 ExFreePool(IrpContext
->InputReportBuffer
);
365 // remove us from pending list
367 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
370 // remove from pending list
372 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
375 // insert into completed list
377 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
382 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
385 // complete original request
387 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
392 ExFreePool(IrpContext
);
397 return STATUS_MORE_PROCESSING_REQUIRED
;
402 IN PHIDCLASS_FILEOP_CONTEXT Context
)
406 PLIST_ENTRY ListEntry
;
411 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
416 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
421 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
426 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
432 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
442 IN PDEVICE_OBJECT DeviceObject
,
444 IN PHIDCLASS_FILEOP_CONTEXT Context
,
445 IN ULONG DeviceIoControlCode
,
446 IN ULONG BufferLength
,
448 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
451 PIO_STACK_LOCATION IoStack
;
452 PHIDCLASS_IRP_CONTEXT IrpContext
;
453 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
456 // get an irp from fresh list
458 Irp
= HidClass_GetIrp(Context
);
464 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
470 return STATUS_INSUFFICIENT_RESOURCES
;
478 IoReuseIrp(Irp
, STATUS_SUCCESS
);
482 // allocate completion context
484 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
491 return STATUS_INSUFFICIENT_RESOURCES
;
495 // get device extension
497 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
498 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
503 ASSERT(PDODeviceExtension
->CollectionIndex
< PDODeviceExtension
->Common
.DeviceDescription
.CollectionDescLength
);
504 ASSERT(PDODeviceExtension
->CollectionIndex
< PDODeviceExtension
->Common
.DeviceDescription
.ReportIDsLength
);
505 ASSERT(PDODeviceExtension
->Common
.DeviceDescription
.ReportIDs
[PDODeviceExtension
->CollectionIndex
].InputLength
> 0);
506 ASSERT(PDODeviceExtension
->Common
.DeviceDescription
.CollectionDesc
[PDODeviceExtension
->CollectionIndex
].InputLength
== BufferLength
);
511 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
512 IrpContext
->InputReportBufferLength
= PDODeviceExtension
->Common
.DeviceDescription
.ReportIDs
[PDODeviceExtension
->CollectionIndex
].InputLength
;
513 IrpContext
->OriginalIrp
= RequestIrp
;
514 IrpContext
->FileOp
= Context
;
519 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
520 if (!IrpContext
->InputReportBuffer
)
526 ExFreePool(IrpContext
);
527 return STATUS_INSUFFICIENT_RESOURCES
;
531 // get stack location
533 IoStack
= IoGetNextIrpStackLocation(Irp
);
536 // init stack location
538 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
539 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
540 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
541 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
542 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
543 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
544 IoStack
->DeviceObject
= DeviceObject
;
550 *OutIrpContext
= IrpContext
;
555 return STATUS_SUCCESS
;
562 IN PDEVICE_OBJECT DeviceObject
,
565 PIO_STACK_LOCATION IoStack
;
566 PHIDCLASS_FILEOP_CONTEXT Context
;
570 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
571 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
574 // get current stack location
576 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
579 // get device extension
581 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
582 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
587 ASSERT(IoStack
->FileObject
);
588 ASSERT(IoStack
->FileObject
->FsContext
);
593 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
597 // FIXME support polled devices
599 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
604 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
605 if (!NT_SUCCESS(Status
))
610 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
611 Irp
->IoStatus
.Status
= Status
;
612 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
619 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
622 // insert irp into pending list
624 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
627 // set completion routine
629 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
632 // make next location current
634 IoSetNextIrpStackLocation(NewIrp
);
639 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
644 IoMarkIrpPending(Irp
);
647 // lets dispatch the request
649 ASSERT(Context
->DeviceExtension
);
650 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
655 return STATUS_PENDING
;
661 IN PDEVICE_OBJECT DeviceObject
,
666 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
667 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
668 return STATUS_NOT_IMPLEMENTED
;
673 HidClass_DeviceControl(
674 IN PDEVICE_OBJECT DeviceObject
,
677 PIO_STACK_LOCATION IoStack
;
678 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
679 PHID_COLLECTION_INFORMATION CollectionInformation
;
682 // get device extension
684 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
687 // get stack location
689 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
691 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
693 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
696 // check if output buffer is big enough
698 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
701 // invalid buffer size
703 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
704 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
705 return STATUS_INVALID_BUFFER_SIZE
;
711 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
712 ASSERT(CollectionInformation
);
715 // init result buffer
717 CollectionInformation
->DescriptorSize
= CommonDeviceExtension
->DeviceDescription
.CollectionDesc
[0].PreparsedDataLength
; //FIXME which collection is to be retrieved for composite devices / multi collection devices?
718 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
719 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
720 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
721 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
726 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
727 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
728 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
729 return STATUS_SUCCESS
;
731 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
734 // FIXME: which collection to use for composite / multi collection devices...
738 // check if output buffer is big enough
740 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CommonDeviceExtension
->DeviceDescription
.CollectionDesc
[0].PreparsedDataLength
)
743 // invalid buffer size
745 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
746 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
747 return STATUS_INVALID_BUFFER_SIZE
;
753 ASSERT(Irp
->UserBuffer
);
754 RtlCopyMemory(Irp
->UserBuffer
, CommonDeviceExtension
->DeviceDescription
.CollectionDesc
[0].PreparsedData
, CommonDeviceExtension
->DeviceDescription
.CollectionDesc
[0].PreparsedDataLength
);
759 Irp
->IoStatus
.Information
= CommonDeviceExtension
->DeviceDescription
.CollectionDesc
[0].PreparsedDataLength
;
760 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
761 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
762 return STATUS_SUCCESS
;
766 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
767 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
768 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
769 return STATUS_NOT_IMPLEMENTED
;
776 HidClass_InternalDeviceControl(
777 IN PDEVICE_OBJECT DeviceObject
,
782 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
783 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
784 return STATUS_NOT_IMPLEMENTED
;
791 IN PDEVICE_OBJECT DeviceObject
,
796 return STATUS_NOT_IMPLEMENTED
;
802 IN PDEVICE_OBJECT DeviceObject
,
805 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
808 // get common device extension
810 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
813 // check type of device object
815 if (CommonDeviceExtension
->IsFDO
)
820 return HidClassFDO_PnP(DeviceObject
, Irp
);
827 return HidClassPDO_PnP(DeviceObject
, Irp
);
833 HidClass_DispatchDefault(
834 IN PDEVICE_OBJECT DeviceObject
,
837 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
840 // get common device extension
842 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
845 // FIXME: support PDO
847 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
850 // skip current irp stack location
852 IoSkipCurrentIrpStackLocation(Irp
);
855 // dispatch to lower device object
857 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
864 IN PDEVICE_OBJECT DeviceObject
,
867 PIO_STACK_LOCATION IoStack
;
870 // get current stack location
872 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
873 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
876 // dispatch request based on major function
878 switch(IoStack
->MajorFunction
)
881 return HidClass_Create(DeviceObject
, Irp
);
883 return HidClass_Close(DeviceObject
, Irp
);
885 return HidClass_Read(DeviceObject
, Irp
);
887 return HidClass_Write(DeviceObject
, Irp
);
888 case IRP_MJ_DEVICE_CONTROL
:
889 return HidClass_DeviceControl(DeviceObject
, Irp
);
890 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
891 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
893 return HidClass_Power(DeviceObject
, Irp
);
895 return HidClass_PnP(DeviceObject
, Irp
);
897 return HidClass_DispatchDefault(DeviceObject
, Irp
);
903 HidRegisterMinidriver(
904 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
907 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
909 /* check if the version matches */
910 if (MinidriverRegistration
->Revision
> HID_REVISION
)
912 /* revision mismatch */
914 return STATUS_REVISION_MISMATCH
;
917 /* now allocate the driver object extension */
918 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
919 if (!NT_SUCCESS(Status
))
921 /* failed to allocate driver extension */
926 /* zero driver extension */
927 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
929 /* init driver extension */
930 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
931 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
932 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
933 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
934 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
936 /* copy driver dispatch routines */
937 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
939 /* initialize lock */
940 KeInitializeSpinLock(&DriverExtension
->Lock
);
942 /* now replace dispatch routines */
943 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
944 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
945 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
946 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
947 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
948 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
949 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
950 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
951 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
952 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
955 return STATUS_SUCCESS
;