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
)
143 // only supported for PDO
145 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
146 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
147 return STATUS_UNSUCCESSFUL
;
150 // ReactOS PnP manager [...]
152 DPRINT1("[HIDCLASS] PnP HACK\n");
153 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
154 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
155 return STATUS_SUCCESS
;
162 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
165 // get device extension
167 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)CommonDeviceExtension
;
170 // get stack location
172 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
174 DPRINT1("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
175 DPRINT1("Options %x\n", IoStack
->Parameters
.Create
.Options
);
176 DPRINT1("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
181 Context
= (PHIDCLASS_FILEOP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
187 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
188 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
189 return STATUS_INSUFFICIENT_RESOURCES
;
195 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
196 Context
->DeviceExtension
= PDODeviceExtension
;
197 KeInitializeSpinLock(&Context
->Lock
);
198 InitializeListHead(&Context
->ReadPendingIrpListHead
);
199 InitializeListHead(&Context
->IrpCompletedListHead
);
204 ASSERT(IoStack
->FileObject
);
205 IoStack
->FileObject
->FsContext
= (PVOID
)Context
;
210 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
211 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
212 return STATUS_SUCCESS
;
218 IN PDEVICE_OBJECT DeviceObject
,
221 PIO_STACK_LOCATION IoStack
;
222 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
223 PHIDCLASS_IRP_CONTEXT IrpContext
;
226 // get device extension
228 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
231 // is it a FDO request
233 if (CommonDeviceExtension
->IsFDO
)
236 // how did the request get there
238 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
239 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
240 return STATUS_INVALID_PARAMETER_1
;
244 // get stack location
246 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
251 ASSERT(IoStack
->FileObject
);
252 ASSERT(IoStack
->FileObject
->FsContext
);
257 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)IoStack
->FileObject
->FsContext
;
260 // cancel pending irps
267 IoStack
->FileObject
->FsContext
= NULL
;
272 ExFreePool(IrpContext
);
277 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
278 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
279 return STATUS_SUCCESS
;
283 HidClass_GetSystemAddress(
291 if (ReportMDL
->MdlFlags
& (MDL_SOURCE_IS_NONPAGED_POOL
| MDL_MAPPED_TO_SYSTEM_VA
))
294 // buffer is non paged pool
296 return ReportMDL
->MappedSystemVa
;
303 return MmMapLockedPages(ReportMDL
, KernelMode
);
309 HidClass_ReadCompleteIrp(
310 IN PDEVICE_OBJECT DeviceObject
,
314 PHIDCLASS_IRP_CONTEXT IrpContext
;
318 PHIDP_COLLECTION_DESC CollectionDescription
;
319 PHIDP_REPORT_IDS ReportDescription
;
324 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)Ctx
;
326 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
327 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
328 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
329 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
330 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
331 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
332 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
337 if (Irp
->IoStatus
.Information
)
342 Address
= (PUCHAR
)HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
346 // reports may have a report id prepended
351 // get collection description
353 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
354 ASSERT(CollectionDescription
);
357 // get report description
359 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
360 ASSERT(ReportDescription
);
362 if (CollectionDescription
&& ReportDescription
)
367 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
368 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
374 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
379 // copy result status
381 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
382 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
385 // free input report buffer
387 ExFreePool(IrpContext
->InputReportBuffer
);
390 // remove us from pending list
392 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
395 // remove from pending list
397 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
400 // insert into completed list
402 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
407 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
410 // complete original request
412 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
417 ExFreePool(IrpContext
);
422 return STATUS_MORE_PROCESSING_REQUIRED
;
427 IN PHIDCLASS_FILEOP_CONTEXT Context
)
431 PLIST_ENTRY ListEntry
;
436 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
441 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
446 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
451 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
457 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
467 IN PDEVICE_OBJECT DeviceObject
,
469 IN PHIDCLASS_FILEOP_CONTEXT Context
,
470 IN ULONG DeviceIoControlCode
,
471 IN ULONG BufferLength
,
473 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
476 PIO_STACK_LOCATION IoStack
;
477 PHIDCLASS_IRP_CONTEXT IrpContext
;
478 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
479 PHIDP_COLLECTION_DESC CollectionDescription
;
480 PHIDP_REPORT_IDS ReportDescription
;
483 // get an irp from fresh list
485 Irp
= HidClass_GetIrp(Context
);
491 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
497 return STATUS_INSUFFICIENT_RESOURCES
;
505 IoReuseIrp(Irp
, STATUS_SUCCESS
);
509 // allocate completion context
511 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
518 return STATUS_INSUFFICIENT_RESOURCES
;
522 // get device extension
524 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
525 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
530 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
531 IrpContext
->OriginalIrp
= RequestIrp
;
532 IrpContext
->FileOp
= Context
;
535 // get collection description
537 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
538 ASSERT(CollectionDescription
);
541 // get report description
543 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
544 ASSERT(ReportDescription
);
549 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
552 // store report length
554 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
559 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
560 if (!IrpContext
->InputReportBuffer
)
566 ExFreePool(IrpContext
);
567 return STATUS_INSUFFICIENT_RESOURCES
;
571 // get stack location
573 IoStack
= IoGetNextIrpStackLocation(Irp
);
576 // init stack location
578 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
579 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
580 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
581 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
582 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
583 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
584 IoStack
->DeviceObject
= DeviceObject
;
590 *OutIrpContext
= IrpContext
;
595 return STATUS_SUCCESS
;
602 IN PDEVICE_OBJECT DeviceObject
,
605 PIO_STACK_LOCATION IoStack
;
606 PHIDCLASS_FILEOP_CONTEXT Context
;
610 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
611 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
614 // get current stack location
616 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
619 // get device extension
621 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
622 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
627 ASSERT(IoStack
->FileObject
);
628 ASSERT(IoStack
->FileObject
->FsContext
);
633 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
637 // FIXME support polled devices
639 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
644 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
645 if (!NT_SUCCESS(Status
))
650 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
651 Irp
->IoStatus
.Status
= Status
;
652 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
659 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
662 // insert irp into pending list
664 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
667 // set completion routine
669 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
672 // make next location current
674 IoSetNextIrpStackLocation(NewIrp
);
679 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
684 IoMarkIrpPending(Irp
);
687 // lets dispatch the request
689 ASSERT(Context
->DeviceExtension
);
690 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
695 return STATUS_PENDING
;
701 IN PDEVICE_OBJECT DeviceObject
,
706 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
707 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
708 return STATUS_NOT_IMPLEMENTED
;
713 HidClass_DeviceControl(
714 IN PDEVICE_OBJECT DeviceObject
,
717 PIO_STACK_LOCATION IoStack
;
718 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
719 PHID_COLLECTION_INFORMATION CollectionInformation
;
720 PHIDP_COLLECTION_DESC CollectionDescription
;
721 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
724 // get device extension
726 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
727 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
730 // get pdo device extension
732 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
735 // get stack location
737 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
739 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
741 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
744 // check if output buffer is big enough
746 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
749 // invalid buffer size
751 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
752 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
753 return STATUS_INVALID_BUFFER_SIZE
;
759 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
760 ASSERT(CollectionInformation
);
763 // get collection description
765 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
766 ASSERT(CollectionDescription
);
769 // init result buffer
771 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
772 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
773 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
774 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
775 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
780 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
781 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
782 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
783 return STATUS_SUCCESS
;
785 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
788 // get collection description
790 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
791 ASSERT(CollectionDescription
);
794 // check if output buffer is big enough
796 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
799 // invalid buffer size
801 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
802 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
803 return STATUS_INVALID_BUFFER_SIZE
;
809 ASSERT(Irp
->UserBuffer
);
810 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
815 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
816 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
817 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
818 return STATUS_SUCCESS
;
822 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
823 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
824 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
825 return STATUS_NOT_IMPLEMENTED
;
832 HidClass_InternalDeviceControl(
833 IN PDEVICE_OBJECT DeviceObject
,
838 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
839 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
840 return STATUS_NOT_IMPLEMENTED
;
847 IN PDEVICE_OBJECT DeviceObject
,
852 return STATUS_NOT_IMPLEMENTED
;
858 IN PDEVICE_OBJECT DeviceObject
,
861 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
864 // get common device extension
866 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
869 // check type of device object
871 if (CommonDeviceExtension
->IsFDO
)
876 return HidClassFDO_PnP(DeviceObject
, Irp
);
883 return HidClassPDO_PnP(DeviceObject
, Irp
);
889 HidClass_DispatchDefault(
890 IN PDEVICE_OBJECT DeviceObject
,
893 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
896 // get common device extension
898 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
901 // FIXME: support PDO
903 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
906 // skip current irp stack location
908 IoSkipCurrentIrpStackLocation(Irp
);
911 // dispatch to lower device object
913 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
920 IN PDEVICE_OBJECT DeviceObject
,
923 PIO_STACK_LOCATION IoStack
;
926 // get current stack location
928 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
929 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
932 // dispatch request based on major function
934 switch(IoStack
->MajorFunction
)
937 return HidClass_Create(DeviceObject
, Irp
);
939 return HidClass_Close(DeviceObject
, Irp
);
941 return HidClass_Read(DeviceObject
, Irp
);
943 return HidClass_Write(DeviceObject
, Irp
);
944 case IRP_MJ_DEVICE_CONTROL
:
945 return HidClass_DeviceControl(DeviceObject
, Irp
);
946 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
947 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
949 return HidClass_Power(DeviceObject
, Irp
);
951 return HidClass_PnP(DeviceObject
, Irp
);
953 return HidClass_DispatchDefault(DeviceObject
, Irp
);
959 HidRegisterMinidriver(
960 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
963 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
965 /* check if the version matches */
966 if (MinidriverRegistration
->Revision
> HID_REVISION
)
968 /* revision mismatch */
970 return STATUS_REVISION_MISMATCH
;
973 /* now allocate the driver object extension */
974 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
975 if (!NT_SUCCESS(Status
))
977 /* failed to allocate driver extension */
982 /* zero driver extension */
983 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
985 /* init driver extension */
986 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
987 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
988 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
989 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
990 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
992 /* copy driver dispatch routines */
993 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
995 /* initialize lock */
996 KeInitializeSpinLock(&DriverExtension
->Lock
);
998 /* now replace dispatch routines */
999 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1000 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1001 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1002 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1003 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1004 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1005 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1006 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1007 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1008 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1011 return STATUS_SUCCESS
;