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
)
125 IN PDEVICE_OBJECT DeviceObject
,
128 PIO_STACK_LOCATION IoStack
;
129 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
130 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
131 PHIDCLASS_FILEOP_CONTEXT Context
;
134 // get device extension
136 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
137 if (CommonDeviceExtension
->IsFDO
)
142 // only supported for PDO
144 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
145 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
146 return STATUS_UNSUCCESSFUL
;
149 // ReactOS PnP manager [...]
151 DPRINT1("[HIDCLASS] PnP HACK\n");
152 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
153 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
154 return STATUS_SUCCESS
;
161 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
164 // get device extension
166 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)CommonDeviceExtension
;
169 // get stack location
171 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
173 DPRINT1("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
174 DPRINT1("Options %x\n", IoStack
->Parameters
.Create
.Options
);
175 DPRINT1("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
180 Context
= (PHIDCLASS_FILEOP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
186 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
187 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
188 return STATUS_INSUFFICIENT_RESOURCES
;
194 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
195 Context
->DeviceExtension
= PDODeviceExtension
;
196 KeInitializeSpinLock(&Context
->Lock
);
197 InitializeListHead(&Context
->ReadPendingIrpListHead
);
198 InitializeListHead(&Context
->IrpCompletedListHead
);
203 ASSERT(IoStack
->FileObject
);
204 IoStack
->FileObject
->FsContext
= (PVOID
)Context
;
209 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
210 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
211 return STATUS_SUCCESS
;
217 IN PDEVICE_OBJECT DeviceObject
,
220 PIO_STACK_LOCATION IoStack
;
221 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
222 PHIDCLASS_IRP_CONTEXT IrpContext
;
225 // get device extension
227 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
230 // is it a FDO request
232 if (CommonDeviceExtension
->IsFDO
)
235 // how did the request get there
237 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
238 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
239 return STATUS_INVALID_PARAMETER_1
;
243 // get stack location
245 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
250 ASSERT(IoStack
->FileObject
);
251 ASSERT(IoStack
->FileObject
->FsContext
);
256 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)IoStack
->FileObject
->FsContext
;
259 // cancel pending irps
266 IoStack
->FileObject
->FsContext
= NULL
;
271 ExFreePool(IrpContext
);
276 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
277 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
278 return STATUS_SUCCESS
;
282 HidClass_GetSystemAddress(
290 if (ReportMDL
->MdlFlags
& (MDL_SOURCE_IS_NONPAGED_POOL
| MDL_MAPPED_TO_SYSTEM_VA
))
293 // buffer is non paged pool
295 return ReportMDL
->MappedSystemVa
;
302 return MmMapLockedPages(ReportMDL
, KernelMode
);
308 HidClass_ReadCompleteIrp(
309 IN PDEVICE_OBJECT DeviceObject
,
313 PHIDCLASS_IRP_CONTEXT IrpContext
;
317 PHIDP_COLLECTION_DESC CollectionDescription
;
318 PHIDP_REPORT_IDS ReportDescription
;
323 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)Ctx
;
325 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
326 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
327 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
328 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
329 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
330 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
331 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
336 if (Irp
->IoStatus
.Information
)
341 Address
= (PUCHAR
)HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
345 // reports may have a report id prepended
350 // get collection description
352 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
353 ASSERT(CollectionDescription
);
356 // get report description
358 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
359 ASSERT(ReportDescription
);
361 if (CollectionDescription
&& ReportDescription
)
366 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
367 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
373 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
378 // copy result status
380 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
381 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
384 // free input report buffer
386 ExFreePool(IrpContext
->InputReportBuffer
);
389 // remove us from pending list
391 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
394 // remove from pending list
396 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
399 // insert into completed list
401 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
406 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
409 // complete original request
411 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
416 ExFreePool(IrpContext
);
421 return STATUS_MORE_PROCESSING_REQUIRED
;
426 IN PHIDCLASS_FILEOP_CONTEXT Context
)
430 PLIST_ENTRY ListEntry
;
435 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
440 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
445 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
450 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
456 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
466 IN PDEVICE_OBJECT DeviceObject
,
468 IN PHIDCLASS_FILEOP_CONTEXT Context
,
469 IN ULONG DeviceIoControlCode
,
470 IN ULONG BufferLength
,
472 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
475 PIO_STACK_LOCATION IoStack
;
476 PHIDCLASS_IRP_CONTEXT IrpContext
;
477 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
478 PHIDP_COLLECTION_DESC CollectionDescription
;
479 PHIDP_REPORT_IDS ReportDescription
;
482 // get an irp from fresh list
484 Irp
= HidClass_GetIrp(Context
);
490 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
496 return STATUS_INSUFFICIENT_RESOURCES
;
504 IoReuseIrp(Irp
, STATUS_SUCCESS
);
508 // allocate completion context
510 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
517 return STATUS_INSUFFICIENT_RESOURCES
;
521 // get device extension
523 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
524 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
529 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
530 IrpContext
->OriginalIrp
= RequestIrp
;
531 IrpContext
->FileOp
= Context
;
534 // get collection description
536 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
537 ASSERT(CollectionDescription
);
540 // get report description
542 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
543 ASSERT(ReportDescription
);
548 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
551 // store report length
553 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
558 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
559 if (!IrpContext
->InputReportBuffer
)
565 ExFreePool(IrpContext
);
566 return STATUS_INSUFFICIENT_RESOURCES
;
570 // get stack location
572 IoStack
= IoGetNextIrpStackLocation(Irp
);
575 // init stack location
577 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
578 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
579 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
580 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
581 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
582 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
583 IoStack
->DeviceObject
= DeviceObject
;
589 *OutIrpContext
= IrpContext
;
594 return STATUS_SUCCESS
;
601 IN PDEVICE_OBJECT DeviceObject
,
604 PIO_STACK_LOCATION IoStack
;
605 PHIDCLASS_FILEOP_CONTEXT Context
;
609 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
610 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
613 // get current stack location
615 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
618 // get device extension
620 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
621 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
626 ASSERT(IoStack
->FileObject
);
627 ASSERT(IoStack
->FileObject
->FsContext
);
632 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
636 // FIXME support polled devices
638 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
643 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
644 if (!NT_SUCCESS(Status
))
649 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
650 Irp
->IoStatus
.Status
= Status
;
651 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
658 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
661 // insert irp into pending list
663 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
666 // set completion routine
668 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
671 // make next location current
673 IoSetNextIrpStackLocation(NewIrp
);
678 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
683 IoMarkIrpPending(Irp
);
686 // lets dispatch the request
688 ASSERT(Context
->DeviceExtension
);
689 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
694 return STATUS_PENDING
;
700 IN PDEVICE_OBJECT DeviceObject
,
705 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
706 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
707 return STATUS_NOT_IMPLEMENTED
;
712 HidClass_DeviceControl(
713 IN PDEVICE_OBJECT DeviceObject
,
716 PIO_STACK_LOCATION IoStack
;
717 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
718 PHID_COLLECTION_INFORMATION CollectionInformation
;
719 PHIDP_COLLECTION_DESC CollectionDescription
;
720 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
723 // get device extension
725 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
728 // only PDO are supported
730 if (CommonDeviceExtension
->IsFDO
)
735 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
736 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
737 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
738 return STATUS_INVALID_PARAMETER_1
;
741 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
744 // get pdo device extension
746 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
749 // get stack location
751 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
753 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
755 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
758 // check if output buffer is big enough
760 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
763 // invalid buffer size
765 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
766 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
767 return STATUS_INVALID_BUFFER_SIZE
;
773 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
774 ASSERT(CollectionInformation
);
777 // get collection description
779 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
780 ASSERT(CollectionDescription
);
783 // init result buffer
785 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
786 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
787 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
788 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
789 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
794 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
795 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
796 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
797 return STATUS_SUCCESS
;
799 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
802 // get collection description
804 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
805 ASSERT(CollectionDescription
);
808 // check if output buffer is big enough
810 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
813 // invalid buffer size
815 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
816 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
817 return STATUS_INVALID_BUFFER_SIZE
;
823 ASSERT(Irp
->UserBuffer
);
824 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
829 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
830 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
831 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
832 return STATUS_SUCCESS
;
836 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
837 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
838 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
839 return STATUS_NOT_IMPLEMENTED
;
846 HidClass_InternalDeviceControl(
847 IN PDEVICE_OBJECT DeviceObject
,
852 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
853 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
854 return STATUS_NOT_IMPLEMENTED
;
861 IN PDEVICE_OBJECT DeviceObject
,
865 return STATUS_NOT_IMPLEMENTED
;
871 IN PDEVICE_OBJECT DeviceObject
,
874 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
877 // get common device extension
879 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
882 // check type of device object
884 if (CommonDeviceExtension
->IsFDO
)
889 return HidClassFDO_PnP(DeviceObject
, Irp
);
896 return HidClassPDO_PnP(DeviceObject
, Irp
);
902 HidClass_DispatchDefault(
903 IN PDEVICE_OBJECT DeviceObject
,
906 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
909 // get common device extension
911 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
914 // FIXME: support PDO
916 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
919 // skip current irp stack location
921 IoSkipCurrentIrpStackLocation(Irp
);
924 // dispatch to lower device object
926 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
933 IN PDEVICE_OBJECT DeviceObject
,
936 PIO_STACK_LOCATION IoStack
;
939 // get current stack location
941 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
942 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
945 // dispatch request based on major function
947 switch(IoStack
->MajorFunction
)
950 return HidClass_Create(DeviceObject
, Irp
);
952 return HidClass_Close(DeviceObject
, Irp
);
954 return HidClass_Read(DeviceObject
, Irp
);
956 return HidClass_Write(DeviceObject
, Irp
);
957 case IRP_MJ_DEVICE_CONTROL
:
958 return HidClass_DeviceControl(DeviceObject
, Irp
);
959 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
960 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
962 return HidClass_Power(DeviceObject
, Irp
);
964 return HidClass_PnP(DeviceObject
, Irp
);
966 return HidClass_DispatchDefault(DeviceObject
, Irp
);
972 HidRegisterMinidriver(
973 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
976 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
978 /* check if the version matches */
979 if (MinidriverRegistration
->Revision
> HID_REVISION
)
981 /* revision mismatch */
983 return STATUS_REVISION_MISMATCH
;
986 /* now allocate the driver object extension */
987 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
988 if (!NT_SUCCESS(Status
))
990 /* failed to allocate driver extension */
995 /* zero driver extension */
996 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
998 /* init driver extension */
999 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1000 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1001 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1002 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1003 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1005 /* copy driver dispatch routines */
1006 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
1008 /* initialize lock */
1009 KeInitializeSpinLock(&DriverExtension
->Lock
);
1011 /* now replace dispatch routines */
1012 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1013 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1014 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1015 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1016 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1017 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1018 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1019 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1020 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1021 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1024 return STATUS_SUCCESS
;