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 DPRINT("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
181 DPRINT("Options %x\n", IoStack
->Parameters
.Create
.Options
);
182 DPRINT("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
);
206 KeInitializeEvent(&Context
->IrpReadComplete
, NotificationEvent
, FALSE
);
211 ASSERT(IoStack
->FileObject
);
212 IoStack
->FileObject
->FsContext
= (PVOID
)Context
;
217 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
218 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
219 return STATUS_SUCCESS
;
225 IN PDEVICE_OBJECT DeviceObject
,
228 PIO_STACK_LOCATION IoStack
;
229 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
230 PHIDCLASS_FILEOP_CONTEXT IrpContext
;
231 BOOLEAN IsRequestPending
= FALSE
;
237 // get device extension
239 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
242 // is it a FDO request
244 if (CommonDeviceExtension
->IsFDO
)
247 // how did the request get there
249 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
250 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
251 return STATUS_INVALID_PARAMETER_1
;
255 // get stack location
257 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
262 ASSERT(IoStack
->FileObject
);
263 ASSERT(IoStack
->FileObject
->FsContext
);
268 IrpContext
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
274 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
276 if (!IsListEmpty(&IrpContext
->ReadPendingIrpListHead
))
281 IsRequestPending
= TRUE
;
287 IrpContext
->StopInProgress
= TRUE
;
292 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
294 if (IsRequestPending
)
297 // wait for request to complete
299 DPRINT1("[HIDCLASS] Waiting for read irp completion...\n");
300 KeWaitForSingleObject(&IrpContext
->IrpReadComplete
, Executive
, KernelMode
, FALSE
, NULL
);
306 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
311 ASSERT(IsListEmpty(&IrpContext
->ReadPendingIrpListHead
));
316 while(!IsListEmpty(&IrpContext
->IrpCompletedListHead
))
321 Entry
= RemoveHeadList(&IrpContext
->IrpCompletedListHead
);
326 ListIrp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
337 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
345 IoStack
->FileObject
->FsContext
= NULL
;
350 ExFreePool(IrpContext
);
355 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
356 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
357 return STATUS_SUCCESS
;
361 HidClass_GetSystemAddress(
369 if (ReportMDL
->MdlFlags
& (MDL_SOURCE_IS_NONPAGED_POOL
| MDL_MAPPED_TO_SYSTEM_VA
))
372 // buffer is non paged pool
374 return ReportMDL
->MappedSystemVa
;
381 return MmMapLockedPages(ReportMDL
, KernelMode
);
387 HidClass_ReadCompleteIrp(
388 IN PDEVICE_OBJECT DeviceObject
,
392 PHIDCLASS_IRP_CONTEXT IrpContext
;
396 PHIDP_COLLECTION_DESC CollectionDescription
;
397 PHIDP_REPORT_IDS ReportDescription
;
403 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)Ctx
;
405 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
406 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
407 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
408 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
409 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
410 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
411 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
416 if (Irp
->IoStatus
.Information
)
421 Address
= (PUCHAR
)HidClass_GetSystemAddress(IrpContext
->OriginalIrp
->MdlAddress
);
425 // reports may have a report id prepended
430 // get collection description
432 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
433 ASSERT(CollectionDescription
);
436 // get report description
438 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
439 ASSERT(ReportDescription
);
441 if (CollectionDescription
&& ReportDescription
)
446 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
447 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
453 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
458 // copy result status
460 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
461 Irp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
464 // free input report buffer
466 ExFreePool(IrpContext
->InputReportBuffer
);
469 // remove us from pending list
471 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
474 // remove from pending list
476 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
481 IsEmpty
= IsListEmpty(&IrpContext
->FileOp
->ReadPendingIrpListHead
);
484 // insert into completed list
486 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
491 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
494 // complete original request
496 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
499 DPRINT("StopInProgress %x IsEmpty %x\n", IrpContext
->FileOp
->StopInProgress
, IsEmpty
);
500 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
505 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
506 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
509 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
514 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
515 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
521 ExFreePool(IrpContext
);
526 return STATUS_MORE_PROCESSING_REQUIRED
;
531 IN PHIDCLASS_FILEOP_CONTEXT Context
)
535 PLIST_ENTRY ListEntry
;
540 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
545 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
550 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
555 Irp
= (PIRP
)CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
561 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
571 IN PDEVICE_OBJECT DeviceObject
,
573 IN PHIDCLASS_FILEOP_CONTEXT Context
,
574 IN ULONG DeviceIoControlCode
,
575 IN ULONG BufferLength
,
577 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
580 PIO_STACK_LOCATION IoStack
;
581 PHIDCLASS_IRP_CONTEXT IrpContext
;
582 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
583 PHIDP_COLLECTION_DESC CollectionDescription
;
584 PHIDP_REPORT_IDS ReportDescription
;
587 // get an irp from fresh list
589 Irp
= HidClass_GetIrp(Context
);
595 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
601 return STATUS_INSUFFICIENT_RESOURCES
;
609 IoReuseIrp(Irp
, STATUS_SUCCESS
);
613 // allocate completion context
615 IrpContext
= (PHIDCLASS_IRP_CONTEXT
)ExAllocatePool(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
));
622 return STATUS_INSUFFICIENT_RESOURCES
;
626 // get device extension
628 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
629 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
634 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
635 IrpContext
->OriginalIrp
= RequestIrp
;
636 IrpContext
->FileOp
= Context
;
639 // get collection description
641 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
642 ASSERT(CollectionDescription
);
645 // get report description
647 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
, IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
648 ASSERT(ReportDescription
);
653 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
655 if (Context
->StopInProgress
)
660 DPRINT1("[HIDCLASS] Stop In Progress\n");
661 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
662 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
663 return STATUS_CANCELLED
;
669 // store report length
671 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
676 IrpContext
->InputReportBuffer
= ExAllocatePool(NonPagedPool
, IrpContext
->InputReportBufferLength
);
677 if (!IrpContext
->InputReportBuffer
)
683 ExFreePool(IrpContext
);
684 return STATUS_INSUFFICIENT_RESOURCES
;
688 // get stack location
690 IoStack
= IoGetNextIrpStackLocation(Irp
);
693 // init stack location
695 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
696 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
697 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
698 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
699 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
700 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
701 IoStack
->DeviceObject
= DeviceObject
;
707 *OutIrpContext
= IrpContext
;
712 return STATUS_SUCCESS
;
719 IN PDEVICE_OBJECT DeviceObject
,
722 PIO_STACK_LOCATION IoStack
;
723 PHIDCLASS_FILEOP_CONTEXT Context
;
727 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
728 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
731 // get current stack location
733 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
736 // get device extension
738 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
739 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
744 ASSERT(IoStack
->FileObject
);
745 ASSERT(IoStack
->FileObject
->FsContext
);
750 Context
= (PHIDCLASS_FILEOP_CONTEXT
)IoStack
->FileObject
->FsContext
;
754 // FIXME support polled devices
756 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
758 if (Context
->StopInProgress
)
763 DPRINT1("[HIDCLASS] Stop In Progress\n");
764 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
765 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
766 return STATUS_CANCELLED
;
774 Status
= HidClass_BuildIrp(DeviceObject
, Irp
, Context
, IOCTL_HID_READ_REPORT
, IoStack
->Parameters
.Read
.Length
, &NewIrp
, &NewIrpContext
);
775 if (!NT_SUCCESS(Status
))
780 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
781 Irp
->IoStatus
.Status
= Status
;
782 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
789 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
792 // insert irp into pending list
794 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
797 // set completion routine
799 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
802 // make next location current
804 IoSetNextIrpStackLocation(NewIrp
);
809 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
814 IoMarkIrpPending(Irp
);
817 // lets dispatch the request
819 ASSERT(Context
->DeviceExtension
);
820 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
825 return STATUS_PENDING
;
831 IN PDEVICE_OBJECT DeviceObject
,
836 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
837 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
838 return STATUS_NOT_IMPLEMENTED
;
843 HidClass_DeviceControl(
844 IN PDEVICE_OBJECT DeviceObject
,
847 PIO_STACK_LOCATION IoStack
;
848 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
849 PHID_COLLECTION_INFORMATION CollectionInformation
;
850 PHIDP_COLLECTION_DESC CollectionDescription
;
851 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
854 // get device extension
856 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
859 // only PDO are supported
861 if (CommonDeviceExtension
->IsFDO
)
866 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
867 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
868 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
869 return STATUS_INVALID_PARAMETER_1
;
872 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
875 // get pdo device extension
877 PDODeviceExtension
= (PHIDCLASS_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
880 // get stack location
882 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
884 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
886 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
889 // check if output buffer is big enough
891 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
894 // invalid buffer size
896 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
897 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
898 return STATUS_INVALID_BUFFER_SIZE
;
904 CollectionInformation
= (PHID_COLLECTION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
905 ASSERT(CollectionInformation
);
908 // get collection description
910 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
911 ASSERT(CollectionDescription
);
914 // init result buffer
916 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
917 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
918 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
919 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
920 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
925 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
926 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
927 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
928 return STATUS_SUCCESS
;
930 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
933 // get collection description
935 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
, PDODeviceExtension
->CollectionNumber
);
936 ASSERT(CollectionDescription
);
939 // check if output buffer is big enough
941 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
944 // invalid buffer size
946 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
947 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
948 return STATUS_INVALID_BUFFER_SIZE
;
954 ASSERT(Irp
->UserBuffer
);
955 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
960 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
961 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
962 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
963 return STATUS_SUCCESS
;
967 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
968 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
969 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
970 return STATUS_NOT_IMPLEMENTED
;
977 HidClass_InternalDeviceControl(
978 IN PDEVICE_OBJECT DeviceObject
,
983 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
984 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
985 return STATUS_NOT_IMPLEMENTED
;
992 IN PDEVICE_OBJECT DeviceObject
,
996 return STATUS_NOT_IMPLEMENTED
;
1002 IN PDEVICE_OBJECT DeviceObject
,
1005 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1008 // get common device extension
1010 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1013 // check type of device object
1015 if (CommonDeviceExtension
->IsFDO
)
1020 return HidClassFDO_PnP(DeviceObject
, Irp
);
1027 return HidClassPDO_PnP(DeviceObject
, Irp
);
1033 HidClass_DispatchDefault(
1034 IN PDEVICE_OBJECT DeviceObject
,
1037 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1040 // get common device extension
1042 CommonDeviceExtension
= (PHIDCLASS_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1045 // FIXME: support PDO
1047 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
1050 // skip current irp stack location
1052 IoSkipCurrentIrpStackLocation(Irp
);
1055 // dispatch to lower device object
1057 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
1064 IN PDEVICE_OBJECT DeviceObject
,
1067 PIO_STACK_LOCATION IoStack
;
1070 // get current stack location
1072 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1073 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
1076 // dispatch request based on major function
1078 switch(IoStack
->MajorFunction
)
1081 return HidClass_Create(DeviceObject
, Irp
);
1083 return HidClass_Close(DeviceObject
, Irp
);
1085 return HidClass_Read(DeviceObject
, Irp
);
1087 return HidClass_Write(DeviceObject
, Irp
);
1088 case IRP_MJ_DEVICE_CONTROL
:
1089 return HidClass_DeviceControl(DeviceObject
, Irp
);
1090 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1091 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
1093 return HidClass_Power(DeviceObject
, Irp
);
1095 return HidClass_PnP(DeviceObject
, Irp
);
1097 return HidClass_DispatchDefault(DeviceObject
, Irp
);
1103 HidRegisterMinidriver(
1104 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
1107 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
1109 /* check if the version matches */
1110 if (MinidriverRegistration
->Revision
> HID_REVISION
)
1112 /* revision mismatch */
1114 return STATUS_REVISION_MISMATCH
;
1117 /* now allocate the driver object extension */
1118 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
, (PVOID
)ClientIdentificationAddress
, sizeof(HIDCLASS_DRIVER_EXTENSION
), (PVOID
*)&DriverExtension
);
1119 if (!NT_SUCCESS(Status
))
1121 /* failed to allocate driver extension */
1126 /* zero driver extension */
1127 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
1129 /* init driver extension */
1130 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1131 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1132 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1133 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1134 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1136 /* copy driver dispatch routines */
1137 RtlCopyMemory(DriverExtension
->MajorFunction
, MinidriverRegistration
->DriverObject
->MajorFunction
, sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+1));
1139 /* initialize lock */
1140 KeInitializeSpinLock(&DriverExtension
->Lock
);
1142 /* now replace dispatch routines */
1143 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1144 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1145 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1146 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1147 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1148 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1149 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1150 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1151 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1152 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1155 return STATUS_SUCCESS
;