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
.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
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)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
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)CommonDeviceExtension
;
176 // get stack location
178 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
180 DPRINT1("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
181 DPRINT1("Options %x\n", IoStack
->Parameters
.Create
.Options
);
182 DPRINT1("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
187 Context
= (PHIDCLASS_FILEOP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
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
);
210 ASSERT(IoStack
->FileObject
);
211 IoStack
->FileObject
->FsContext
= (PVOID
)Context
;
216 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
217 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
218 return STATUS_SUCCESS
;
224 IN PDEVICE_OBJECT DeviceObject
,
227 PIO_STACK_LOCATION IoStack
;
228 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
229 PHIDCLASS_IRP_CONTEXT IrpContext
;
232 // get device extension
234 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
237 // is it a FDO request
239 if (CommonDeviceExtension
->IsFDO
)
242 // how did the request get there
244 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
245 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
246 return STATUS_INVALID_PARAMETER_1
;
250 // get stack location
252 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
257 ASSERT(IoStack
->FileObject
);
258 ASSERT(IoStack
->FileObject
->FsContext
);
263 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)IoStack
->FileObject
->FsContext
;
266 // cancel pending irps
273 IoStack
->FileObject
->FsContext
= NULL
;
278 ExFreePool(IrpContext
);
283 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
284 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
285 return STATUS_SUCCESS
;
289 HidClass_GetSystemAddress(
297 if (ReportMDL
->MdlFlags
& (MDL_SOURCE_IS_NONPAGED_POOL
| MDL_MAPPED_TO_SYSTEM_VA
))
300 // buffer is non paged pool
302 return ReportMDL
->MappedSystemVa
;
309 return MmMapLockedPages(ReportMDL
, KernelMode
);
315 HidClass_ReadCompleteIrp(
316 IN PDEVICE_OBJECT DeviceObject
,
320 PHIDCLASS_IRP_CONTEXT IrpContext
;
324 PHIDP_COLLECTION_DESC CollectionDescription
;
325 PHIDP_REPORT_IDS ReportDescription
;
330 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)Ctx
;
332 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
333 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
334 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
335 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
336 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
337 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
338 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
343 if (Irp
->IoStatus
.Information
)
348 Address
= (PUCHAR
)HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
352 // reports may have a report id prepended
357 // get collection description
359 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
360 ASSERT(CollectionDescription
);
363 // get report description
365 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
366 ASSERT(ReportDescription
);
368 if (CollectionDescription
&& ReportDescription
)
373 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
374 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
380 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
385 // copy result status
387 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
388 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
391 // free input report buffer
393 ExFreePool(IrpContext
->InputReportBuffer
);
396 // remove us from pending list
398 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
401 // remove from pending list
403 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
406 // insert into completed list
408 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
413 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
416 // complete original request
418 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
423 ExFreePool(IrpContext
);
428 return STATUS_MORE_PROCESSING_REQUIRED
;
433 IN PHIDCLASS_FILEOP_CONTEXT Context
)
437 PLIST_ENTRY ListEntry
;
442 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
447 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
452 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
457 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
463 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
473 IN PDEVICE_OBJECT DeviceObject
,
475 IN PHIDCLASS_FILEOP_CONTEXT Context
,
476 IN ULONG DeviceIoControlCode
,
477 IN ULONG BufferLength
,
479 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
482 PIO_STACK_LOCATION IoStack
;
483 PHIDCLASS_IRP_CONTEXT IrpContext
;
484 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
485 PHIDP_COLLECTION_DESC CollectionDescription
;
486 PHIDP_REPORT_IDS ReportDescription
;
489 // get an irp from fresh list
491 Irp
= HidClass_GetIrp(Context
);
497 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
503 return STATUS_INSUFFICIENT_RESOURCES
;
511 IoReuseIrp(Irp
, STATUS_SUCCESS
);
515 // allocate completion context
517 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
524 return STATUS_INSUFFICIENT_RESOURCES
;
528 // get device extension
530 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
531 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
536 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
537 IrpContext
->OriginalIrp
= RequestIrp
;
538 IrpContext
->FileOp
= Context
;
541 // get collection description
543 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
544 ASSERT(CollectionDescription
);
547 // get report description
549 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
550 ASSERT(ReportDescription
);
555 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
558 // store report length
560 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
565 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
566 if (!IrpContext
->InputReportBuffer
)
572 ExFreePool(IrpContext
);
573 return STATUS_INSUFFICIENT_RESOURCES
;
577 // get stack location
579 IoStack
= IoGetNextIrpStackLocation(Irp
);
582 // init stack location
584 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
585 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
586 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
587 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
588 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
589 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
590 IoStack
->DeviceObject
= DeviceObject
;
596 *OutIrpContext
= IrpContext
;
601 return STATUS_SUCCESS
;
608 IN PDEVICE_OBJECT DeviceObject
,
611 PIO_STACK_LOCATION IoStack
;
612 PHIDCLASS_FILEOP_CONTEXT Context
;
616 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
617 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
620 // get current stack location
622 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
625 // get device extension
627 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
628 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
633 ASSERT(IoStack
->FileObject
);
634 ASSERT(IoStack
->FileObject
->FsContext
);
639 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
643 // FIXME support polled devices
645 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
650 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
651 if (!NT_SUCCESS(Status
))
656 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
657 Irp
->IoStatus
.Status
= Status
;
658 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
665 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
668 // insert irp into pending list
670 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
673 // set completion routine
675 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
678 // make next location current
680 IoSetNextIrpStackLocation(NewIrp
);
685 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
690 IoMarkIrpPending(Irp
);
693 // lets dispatch the request
695 ASSERT(Context
->DeviceExtension
);
696 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
701 return STATUS_PENDING
;
707 IN PDEVICE_OBJECT DeviceObject
,
712 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
713 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
714 return STATUS_NOT_IMPLEMENTED
;
719 HidClass_DeviceControl(
720 IN PDEVICE_OBJECT DeviceObject
,
723 PIO_STACK_LOCATION IoStack
;
724 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
725 PHID_COLLECTION_INFORMATION CollectionInformation
;
726 PHIDP_COLLECTION_DESC CollectionDescription
;
727 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
730 // get device extension
732 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
735 // only PDO are supported
737 if (CommonDeviceExtension
->IsFDO
)
742 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
743 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
744 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
745 return STATUS_INVALID_PARAMETER_1
;
748 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
751 // get pdo device extension
753 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
756 // get stack location
758 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
760 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
762 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
765 // check if output buffer is big enough
767 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
770 // invalid buffer size
772 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
773 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
774 return STATUS_INVALID_BUFFER_SIZE
;
780 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
781 ASSERT(CollectionInformation
);
784 // get collection description
786 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
787 ASSERT(CollectionDescription
);
790 // init result buffer
792 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
793 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
794 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
795 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
796 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
801 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
802 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
803 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
804 return STATUS_SUCCESS
;
806 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
809 // get collection description
811 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
812 ASSERT(CollectionDescription
);
815 // check if output buffer is big enough
817 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
820 // invalid buffer size
822 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
823 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
824 return STATUS_INVALID_BUFFER_SIZE
;
830 ASSERT(Irp
->UserBuffer
);
831 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
836 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
837 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
838 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
839 return STATUS_SUCCESS
;
843 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
844 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
845 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
846 return STATUS_NOT_IMPLEMENTED
;
853 HidClass_InternalDeviceControl(
854 IN PDEVICE_OBJECT DeviceObject
,
859 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
860 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
861 return STATUS_NOT_IMPLEMENTED
;
868 IN PDEVICE_OBJECT DeviceObject
,
872 return STATUS_NOT_IMPLEMENTED
;
878 IN PDEVICE_OBJECT DeviceObject
,
881 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
884 // get common device extension
886 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
889 // check type of device object
891 if (CommonDeviceExtension
->IsFDO
)
896 return HidClassFDO_PnP(DeviceObject
, Irp
);
903 return HidClassPDO_PnP(DeviceObject
, Irp
);
909 HidClass_DispatchDefault(
910 IN PDEVICE_OBJECT DeviceObject
,
913 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
916 // get common device extension
918 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
921 // FIXME: support PDO
923 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
926 // skip current irp stack location
928 IoSkipCurrentIrpStackLocation(Irp
);
931 // dispatch to lower device object
933 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
940 IN PDEVICE_OBJECT DeviceObject
,
943 PIO_STACK_LOCATION IoStack
;
946 // get current stack location
948 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
949 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
952 // dispatch request based on major function
954 switch(IoStack
->MajorFunction
)
957 return HidClass_Create(DeviceObject
, Irp
);
959 return HidClass_Close(DeviceObject
, Irp
);
961 return HidClass_Read(DeviceObject
, Irp
);
963 return HidClass_Write(DeviceObject
, Irp
);
964 case IRP_MJ_DEVICE_CONTROL
:
965 return HidClass_DeviceControl(DeviceObject
, Irp
);
966 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
967 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
969 return HidClass_Power(DeviceObject
, Irp
);
971 return HidClass_PnP(DeviceObject
, Irp
);
973 return HidClass_DispatchDefault(DeviceObject
, Irp
);
979 HidRegisterMinidriver(
980 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
983 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
985 /* check if the version matches */
986 if (MinidriverRegistration
->Revision
> HID_REVISION
)
988 /* revision mismatch */
990 return STATUS_REVISION_MISMATCH
;
993 /* now allocate the driver object extension */
994 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
995 if (!NT_SUCCESS(Status
))
997 /* failed to allocate driver extension */
1002 /* zero driver extension */
1003 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
1005 /* init driver extension */
1006 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1007 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1008 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1009 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1010 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1012 /* copy driver dispatch routines */
1013 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
1015 /* initialize lock */
1016 KeInitializeSpinLock(&DriverExtension
->Lock
);
1018 /* now replace dispatch routines */
1019 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1020 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1021 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1022 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1023 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1024 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1025 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1026 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1027 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1028 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1031 return STATUS_SUCCESS
;