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)
16 static LPWSTR ClientIdentificationAddress
= L
"HIDCLASS";
17 static ULONG HidClassDeviceNumber
= 0;
22 IN PUNICODE_STRING RegistryPath
)
24 return STATUS_SUCCESS
;
31 return STATUS_SUCCESS
;
37 IN PDRIVER_OBJECT DriverObject
,
38 IN PDEVICE_OBJECT PhysicalDeviceObject
)
40 WCHAR CharDeviceName
[64];
42 UNICODE_STRING DeviceName
;
43 PDEVICE_OBJECT NewDeviceObject
;
44 PHIDCLASS_FDO_EXTENSION FDODeviceExtension
;
45 ULONG DeviceExtensionSize
;
46 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
48 /* increment device number */
49 InterlockedIncrement((PLONG
)&HidClassDeviceNumber
);
51 /* construct device name */
52 swprintf(CharDeviceName
, L
"\\Device\\_HID%08x", HidClassDeviceNumber
);
54 /* initialize device name */
55 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
57 /* get driver object extension */
58 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, ClientIdentificationAddress
);
63 return STATUS_DEVICE_CONFIGURATION_ERROR
;
66 /* calculate device extension size */
67 DeviceExtensionSize
= sizeof(HIDCLASS_FDO_EXTENSION
) + DriverExtension
->DeviceExtensionSize
;
69 /* now create the device */
70 Status
= IoCreateDevice(DriverObject
, DeviceExtensionSize
, &DeviceName
, FILE_DEVICE_UNKNOWN
, 0, FALSE
, &NewDeviceObject
);
71 if (!NT_SUCCESS(Status
))
73 /* failed to create device object */
78 /* get device extension */
79 FDODeviceExtension
= NewDeviceObject
->DeviceExtension
;
81 /* zero device extension */
82 RtlZeroMemory(FDODeviceExtension
, sizeof(HIDCLASS_FDO_EXTENSION
));
84 /* initialize device extension */
85 FDODeviceExtension
->Common
.IsFDO
= TRUE
;
86 FDODeviceExtension
->Common
.DriverExtension
= DriverExtension
;
87 FDODeviceExtension
->Common
.HidDeviceExtension
.PhysicalDeviceObject
= PhysicalDeviceObject
;
88 FDODeviceExtension
->Common
.HidDeviceExtension
.MiniDeviceExtension
= (PVOID
)((ULONG_PTR
)FDODeviceExtension
+ sizeof(HIDCLASS_FDO_EXTENSION
));
89 FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
= IoAttachDeviceToDeviceStack(NewDeviceObject
, PhysicalDeviceObject
);
90 if (FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
== NULL
)
93 IoDeleteDevice(NewDeviceObject
);
94 DPRINT1("[HIDCLASS] failed to attach to device stack\n");
95 return STATUS_DEVICE_REMOVED
;
99 ASSERT(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
101 /* increment stack size */
102 NewDeviceObject
->StackSize
++;
104 /* init device object */
105 NewDeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
106 NewDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
108 /* now call driver provided add device routine */
109 ASSERT(DriverExtension
->AddDevice
!= 0);
110 Status
= DriverExtension
->AddDevice(DriverObject
, NewDeviceObject
);
111 if (!NT_SUCCESS(Status
))
114 DPRINT1("HIDCLASS: AddDevice failed with %x\n", Status
);
115 IoDetachDevice(FDODeviceExtension
->Common
.HidDeviceExtension
.NextDeviceObject
);
116 IoDeleteDevice(NewDeviceObject
);
126 HidClassDriverUnload(
127 IN PDRIVER_OBJECT DriverObject
)
135 IN PDEVICE_OBJECT DeviceObject
,
138 PIO_STACK_LOCATION IoStack
;
139 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
140 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
141 PHIDCLASS_FILEOP_CONTEXT Context
;
144 // get device extension
146 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
147 if (CommonDeviceExtension
->IsFDO
)
150 // only supported for PDO
152 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
153 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
154 return STATUS_UNSUCCESSFUL
;
160 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
163 // get device extension
165 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
168 // get stack location
170 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
172 DPRINT("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
173 DPRINT("Options %x\n", IoStack
->Parameters
.Create
.Options
);
174 DPRINT("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
179 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
), HIDCLASS_TAG
);
185 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
186 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
187 return STATUS_INSUFFICIENT_RESOURCES
;
193 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
194 Context
->DeviceExtension
= PDODeviceExtension
;
195 KeInitializeSpinLock(&Context
->Lock
);
196 InitializeListHead(&Context
->ReadPendingIrpListHead
);
197 InitializeListHead(&Context
->IrpCompletedListHead
);
198 KeInitializeEvent(&Context
->IrpReadComplete
, NotificationEvent
, FALSE
);
203 ASSERT(IoStack
->FileObject
);
204 IoStack
->FileObject
->FsContext
= 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_FILEOP_CONTEXT IrpContext
;
223 BOOLEAN IsRequestPending
= FALSE
;
229 // get device extension
231 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
234 // is it a FDO request
236 if (CommonDeviceExtension
->IsFDO
)
239 // how did the request get there
241 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
242 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
243 return STATUS_INVALID_PARAMETER_1
;
247 // get stack location
249 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
254 ASSERT(IoStack
->FileObject
);
255 ASSERT(IoStack
->FileObject
->FsContext
);
260 IrpContext
= IoStack
->FileObject
->FsContext
;
266 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
268 if (!IsListEmpty(&IrpContext
->ReadPendingIrpListHead
))
273 IsRequestPending
= TRUE
;
279 IrpContext
->StopInProgress
= TRUE
;
284 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
286 if (IsRequestPending
)
289 // wait for request to complete
291 DPRINT1("[HIDCLASS] Waiting for read irp completion...\n");
292 KeWaitForSingleObject(&IrpContext
->IrpReadComplete
, Executive
, KernelMode
, FALSE
, NULL
);
298 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
303 ASSERT(IsListEmpty(&IrpContext
->ReadPendingIrpListHead
));
308 while (!IsListEmpty(&IrpContext
->IrpCompletedListHead
))
313 Entry
= RemoveHeadList(&IrpContext
->IrpCompletedListHead
);
318 ListIrp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
329 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
334 IoStack
->FileObject
->FsContext
= NULL
;
339 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
344 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
345 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
346 return STATUS_SUCCESS
;
351 HidClass_ReadCompleteIrp(
352 IN PDEVICE_OBJECT DeviceObject
,
356 PHIDCLASS_IRP_CONTEXT IrpContext
;
360 PHIDP_COLLECTION_DESC CollectionDescription
;
361 PHIDP_REPORT_IDS ReportDescription
;
369 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
370 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
371 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
372 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
373 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
374 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
375 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
380 if (Irp
->IoStatus
.Information
)
385 Address
= MmGetSystemAddressForMdlSafe(IrpContext
->OriginalIrp
->MdlAddress
, NormalPagePriority
);
389 // reports may have a report id prepended
394 // get collection description
396 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
397 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
398 ASSERT(CollectionDescription
);
401 // get report description
403 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
404 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
405 ASSERT(ReportDescription
);
407 if (CollectionDescription
&& ReportDescription
)
412 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
413 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
419 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
424 // copy result status
426 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
427 IrpContext
->OriginalIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
430 // free input report buffer
432 ExFreePoolWithTag(IrpContext
->InputReportBuffer
, HIDCLASS_TAG
);
435 // remove us from pending list
437 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
440 // remove from pending list
442 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
447 IsEmpty
= IsListEmpty(&IrpContext
->FileOp
->ReadPendingIrpListHead
);
450 // insert into completed list
452 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
457 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
460 // complete original request
462 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
465 DPRINT("StopInProgress %x IsEmpty %x\n", IrpContext
->FileOp
->StopInProgress
, IsEmpty
);
466 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
471 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
472 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
475 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
480 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
481 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
487 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
492 return STATUS_MORE_PROCESSING_REQUIRED
;
497 IN PHIDCLASS_FILEOP_CONTEXT Context
)
501 PLIST_ENTRY ListEntry
;
506 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
511 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
516 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
521 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
527 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
537 IN PDEVICE_OBJECT DeviceObject
,
539 IN PHIDCLASS_FILEOP_CONTEXT Context
,
540 IN ULONG DeviceIoControlCode
,
541 IN ULONG BufferLength
,
543 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
546 PIO_STACK_LOCATION IoStack
;
547 PHIDCLASS_IRP_CONTEXT IrpContext
;
548 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
549 PHIDP_COLLECTION_DESC CollectionDescription
;
550 PHIDP_REPORT_IDS ReportDescription
;
553 // get an irp from fresh list
555 Irp
= HidClass_GetIrp(Context
);
561 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
567 return STATUS_INSUFFICIENT_RESOURCES
;
575 IoReuseIrp(Irp
, STATUS_SUCCESS
);
579 // allocate completion context
581 IrpContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
), HIDCLASS_TAG
);
588 return STATUS_INSUFFICIENT_RESOURCES
;
592 // get device extension
594 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
595 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
600 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
601 IrpContext
->OriginalIrp
= RequestIrp
;
602 IrpContext
->FileOp
= Context
;
605 // get collection description
607 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
608 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
609 ASSERT(CollectionDescription
);
612 // get report description
614 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
615 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
616 ASSERT(ReportDescription
);
621 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
623 if (Context
->StopInProgress
)
628 DPRINT1("[HIDCLASS] Stop In Progress\n");
629 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
630 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
631 return STATUS_CANCELLED
;
636 // store report length
638 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
643 IrpContext
->InputReportBuffer
= ExAllocatePoolWithTag(NonPagedPool
, IrpContext
->InputReportBufferLength
, HIDCLASS_TAG
);
644 if (!IrpContext
->InputReportBuffer
)
650 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
651 return STATUS_INSUFFICIENT_RESOURCES
;
655 // get stack location
657 IoStack
= IoGetNextIrpStackLocation(Irp
);
660 // init stack location
662 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
663 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
664 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
665 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
666 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
667 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
668 IoStack
->DeviceObject
= DeviceObject
;
674 *OutIrpContext
= IrpContext
;
679 return STATUS_SUCCESS
;
685 IN PDEVICE_OBJECT DeviceObject
,
688 PIO_STACK_LOCATION IoStack
;
689 PHIDCLASS_FILEOP_CONTEXT Context
;
693 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
694 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
697 // get current stack location
699 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
702 // get device extension
704 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
705 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
710 ASSERT(IoStack
->FileObject
);
711 ASSERT(IoStack
->FileObject
->FsContext
);
716 Context
= IoStack
->FileObject
->FsContext
;
720 // FIXME support polled devices
722 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
724 if (Context
->StopInProgress
)
729 DPRINT1("[HIDCLASS] Stop In Progress\n");
730 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
731 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
732 return STATUS_CANCELLED
;
738 Status
= HidClass_BuildIrp(DeviceObject
,
741 IOCTL_HID_READ_REPORT
,
742 IoStack
->Parameters
.Read
.Length
,
745 if (!NT_SUCCESS(Status
))
750 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
751 Irp
->IoStatus
.Status
= Status
;
752 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
759 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
762 // insert irp into pending list
764 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
767 // set completion routine
769 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
772 // make next location current
774 IoSetNextIrpStackLocation(NewIrp
);
779 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
784 IoMarkIrpPending(Irp
);
787 // let's dispatch the request
789 ASSERT(Context
->DeviceExtension
);
790 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
795 return STATUS_PENDING
;
801 IN PDEVICE_OBJECT DeviceObject
,
806 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
807 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
808 return STATUS_NOT_IMPLEMENTED
;
813 HidClass_DeviceControl(
814 IN PDEVICE_OBJECT DeviceObject
,
817 PIO_STACK_LOCATION IoStack
;
818 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
819 PHID_COLLECTION_INFORMATION CollectionInformation
;
820 PHIDP_COLLECTION_DESC CollectionDescription
;
821 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
824 // get device extension
826 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
829 // only PDO are supported
831 if (CommonDeviceExtension
->IsFDO
)
836 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
837 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
838 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
839 return STATUS_INVALID_PARAMETER_1
;
842 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
845 // get pdo device extension
847 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
850 // get stack location
852 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
854 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
856 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
859 // check if output buffer is big enough
861 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
864 // invalid buffer size
866 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
867 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
868 return STATUS_INVALID_BUFFER_SIZE
;
874 CollectionInformation
= Irp
->AssociatedIrp
.SystemBuffer
;
875 ASSERT(CollectionInformation
);
878 // get collection description
880 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
881 PDODeviceExtension
->CollectionNumber
);
882 ASSERT(CollectionDescription
);
885 // init result buffer
887 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
888 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
889 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
890 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
891 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
896 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
897 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
898 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
899 return STATUS_SUCCESS
;
901 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
904 // get collection description
906 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
907 PDODeviceExtension
->CollectionNumber
);
908 ASSERT(CollectionDescription
);
911 // check if output buffer is big enough
913 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
916 // invalid buffer size
918 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
919 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
920 return STATUS_INVALID_BUFFER_SIZE
;
926 ASSERT(Irp
->UserBuffer
);
927 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
932 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
933 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
934 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
935 return STATUS_SUCCESS
;
939 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
940 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
941 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
942 return STATUS_NOT_IMPLEMENTED
;
949 HidClass_InternalDeviceControl(
950 IN PDEVICE_OBJECT DeviceObject
,
955 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
956 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
957 return STATUS_NOT_IMPLEMENTED
;
963 IN PDEVICE_OBJECT DeviceObject
,
966 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
967 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
969 if (CommonDeviceExtension
->IsFDO
)
971 IoCopyCurrentIrpStackLocationToNext(Irp
);
972 return HidClassFDO_DispatchRequest(DeviceObject
, Irp
);
976 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
977 PoStartNextPowerIrp(Irp
);
978 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
979 return STATUS_SUCCESS
;
986 IN PDEVICE_OBJECT DeviceObject
,
989 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
992 // get common device extension
994 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
997 // check type of device object
999 if (CommonDeviceExtension
->IsFDO
)
1004 return HidClassFDO_PnP(DeviceObject
, Irp
);
1011 return HidClassPDO_PnP(DeviceObject
, Irp
);
1017 HidClass_DispatchDefault(
1018 IN PDEVICE_OBJECT DeviceObject
,
1021 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1024 // get common device extension
1026 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
1029 // FIXME: support PDO
1031 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
1034 // skip current irp stack location
1036 IoSkipCurrentIrpStackLocation(Irp
);
1039 // dispatch to lower device object
1041 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
1047 IN PDEVICE_OBJECT DeviceObject
,
1050 PIO_STACK_LOCATION IoStack
;
1053 // get current stack location
1055 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1056 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
1059 // dispatch request based on major function
1061 switch (IoStack
->MajorFunction
)
1064 return HidClass_Create(DeviceObject
, Irp
);
1066 return HidClass_Close(DeviceObject
, Irp
);
1068 return HidClass_Read(DeviceObject
, Irp
);
1070 return HidClass_Write(DeviceObject
, Irp
);
1071 case IRP_MJ_DEVICE_CONTROL
:
1072 return HidClass_DeviceControl(DeviceObject
, Irp
);
1073 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1074 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
1076 return HidClass_Power(DeviceObject
, Irp
);
1078 return HidClass_PnP(DeviceObject
, Irp
);
1080 return HidClass_DispatchDefault(DeviceObject
, Irp
);
1086 HidRegisterMinidriver(
1087 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
1090 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
1092 /* check if the version matches */
1093 if (MinidriverRegistration
->Revision
> HID_REVISION
)
1095 /* revision mismatch */
1097 return STATUS_REVISION_MISMATCH
;
1100 /* now allocate the driver object extension */
1101 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
,
1102 ClientIdentificationAddress
,
1103 sizeof(HIDCLASS_DRIVER_EXTENSION
),
1104 (PVOID
*)&DriverExtension
);
1105 if (!NT_SUCCESS(Status
))
1107 /* failed to allocate driver extension */
1112 /* zero driver extension */
1113 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
1115 /* init driver extension */
1116 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1117 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1118 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1119 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1120 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1122 /* copy driver dispatch routines */
1123 RtlCopyMemory(DriverExtension
->MajorFunction
,
1124 MinidriverRegistration
->DriverObject
->MajorFunction
,
1125 sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+ 1));
1127 /* initialize lock */
1128 KeInitializeSpinLock(&DriverExtension
->Lock
);
1130 /* now replace dispatch routines */
1131 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1132 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1133 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1134 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1135 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1136 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1137 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1138 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1139 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1140 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1143 return STATUS_SUCCESS
;