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
)
152 // only supported for PDO
154 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
155 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
156 return STATUS_UNSUCCESSFUL
;
159 // ReactOS PnP manager [...]
161 DPRINT1("[HIDCLASS] PnP HACK\n");
162 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
163 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
164 return STATUS_SUCCESS
;
171 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
174 // get device extension
176 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
179 // get stack location
181 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
183 DPRINT("ShareAccess %x\n", IoStack
->Parameters
.Create
.ShareAccess
);
184 DPRINT("Options %x\n", IoStack
->Parameters
.Create
.Options
);
185 DPRINT("DesiredAccess %x\n", IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
190 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_FILEOP_CONTEXT
), HIDCLASS_TAG
);
196 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
197 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
198 return STATUS_INSUFFICIENT_RESOURCES
;
204 RtlZeroMemory(Context
, sizeof(HIDCLASS_FILEOP_CONTEXT
));
205 Context
->DeviceExtension
= PDODeviceExtension
;
206 KeInitializeSpinLock(&Context
->Lock
);
207 InitializeListHead(&Context
->ReadPendingIrpListHead
);
208 InitializeListHead(&Context
->IrpCompletedListHead
);
209 KeInitializeEvent(&Context
->IrpReadComplete
, NotificationEvent
, FALSE
);
214 ASSERT(IoStack
->FileObject
);
215 IoStack
->FileObject
->FsContext
= Context
;
220 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
221 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
222 return STATUS_SUCCESS
;
228 IN PDEVICE_OBJECT DeviceObject
,
231 PIO_STACK_LOCATION IoStack
;
232 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
233 PHIDCLASS_FILEOP_CONTEXT IrpContext
;
234 BOOLEAN IsRequestPending
= FALSE
;
240 // get device extension
242 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
245 // is it a FDO request
247 if (CommonDeviceExtension
->IsFDO
)
250 // how did the request get there
252 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
253 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
254 return STATUS_INVALID_PARAMETER_1
;
258 // get stack location
260 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
265 ASSERT(IoStack
->FileObject
);
266 ASSERT(IoStack
->FileObject
->FsContext
);
271 IrpContext
= IoStack
->FileObject
->FsContext
;
277 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
279 if (!IsListEmpty(&IrpContext
->ReadPendingIrpListHead
))
284 IsRequestPending
= TRUE
;
290 IrpContext
->StopInProgress
= TRUE
;
295 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
297 if (IsRequestPending
)
300 // wait for request to complete
302 DPRINT1("[HIDCLASS] Waiting for read irp completion...\n");
303 KeWaitForSingleObject(&IrpContext
->IrpReadComplete
, Executive
, KernelMode
, FALSE
, NULL
);
309 KeAcquireSpinLock(&IrpContext
->Lock
, &OldLevel
);
314 ASSERT(IsListEmpty(&IrpContext
->ReadPendingIrpListHead
));
319 while (!IsListEmpty(&IrpContext
->IrpCompletedListHead
))
324 Entry
= RemoveHeadList(&IrpContext
->IrpCompletedListHead
);
329 ListIrp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
340 KeReleaseSpinLock(&IrpContext
->Lock
, OldLevel
);
345 IoStack
->FileObject
->FsContext
= NULL
;
350 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
355 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
356 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
357 return STATUS_SUCCESS
;
362 HidClass_ReadCompleteIrp(
363 IN PDEVICE_OBJECT DeviceObject
,
367 PHIDCLASS_IRP_CONTEXT IrpContext
;
371 PHIDP_COLLECTION_DESC CollectionDescription
;
372 PHIDP_REPORT_IDS ReportDescription
;
380 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
381 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp
->IoStatus
.Status
);
382 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp
->IoStatus
.Information
);
383 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp
);
384 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext
->InputReportBuffer
);
385 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext
->InputReportBufferLength
);
386 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext
->OriginalIrp
);
391 if (Irp
->IoStatus
.Information
)
396 Address
= MmGetSystemAddressForMdlSafe(IrpContext
->OriginalIrp
->MdlAddress
, NormalPagePriority
);
400 // reports may have a report id prepended
405 // get collection description
407 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
408 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
409 ASSERT(CollectionDescription
);
412 // get report description
414 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
415 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
416 ASSERT(ReportDescription
);
418 if (CollectionDescription
&& ReportDescription
)
423 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
424 Offset
= CollectionDescription
->InputLength
- ReportDescription
->InputLength
;
430 RtlCopyMemory(&Address
[Offset
], IrpContext
->InputReportBuffer
, IrpContext
->InputReportBufferLength
);
435 // copy result status
437 IrpContext
->OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
438 IrpContext
->OriginalIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
441 // free input report buffer
443 ExFreePoolWithTag(IrpContext
->InputReportBuffer
, HIDCLASS_TAG
);
446 // remove us from pending list
448 KeAcquireSpinLock(&IrpContext
->FileOp
->Lock
, &OldLevel
);
451 // remove from pending list
453 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
458 IsEmpty
= IsListEmpty(&IrpContext
->FileOp
->ReadPendingIrpListHead
);
461 // insert into completed list
463 InsertTailList(&IrpContext
->FileOp
->IrpCompletedListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
468 KeReleaseSpinLock(&IrpContext
->FileOp
->Lock
, OldLevel
);
471 // complete original request
473 IoCompleteRequest(IrpContext
->OriginalIrp
, IO_NO_INCREMENT
);
476 DPRINT("StopInProgress %x IsEmpty %x\n", IrpContext
->FileOp
->StopInProgress
, IsEmpty
);
477 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
482 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
483 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
486 if (IrpContext
->FileOp
->StopInProgress
&& IsEmpty
)
491 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n");
492 KeSetEvent(&IrpContext
->FileOp
->IrpReadComplete
, 0, FALSE
);
498 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
503 return STATUS_MORE_PROCESSING_REQUIRED
;
508 IN PHIDCLASS_FILEOP_CONTEXT Context
)
512 PLIST_ENTRY ListEntry
;
517 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
522 if (!IsListEmpty(&Context
->IrpCompletedListHead
))
527 ListEntry
= RemoveHeadList(&Context
->IrpCompletedListHead
);
532 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
538 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
548 IN PDEVICE_OBJECT DeviceObject
,
550 IN PHIDCLASS_FILEOP_CONTEXT Context
,
551 IN ULONG DeviceIoControlCode
,
552 IN ULONG BufferLength
,
554 OUT PHIDCLASS_IRP_CONTEXT
*OutIrpContext
)
557 PIO_STACK_LOCATION IoStack
;
558 PHIDCLASS_IRP_CONTEXT IrpContext
;
559 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
560 PHIDP_COLLECTION_DESC CollectionDescription
;
561 PHIDP_REPORT_IDS ReportDescription
;
564 // get an irp from fresh list
566 Irp
= HidClass_GetIrp(Context
);
572 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
578 return STATUS_INSUFFICIENT_RESOURCES
;
586 IoReuseIrp(Irp
, STATUS_SUCCESS
);
590 // allocate completion context
592 IrpContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(HIDCLASS_IRP_CONTEXT
), HIDCLASS_TAG
);
599 return STATUS_INSUFFICIENT_RESOURCES
;
603 // get device extension
605 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
606 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
611 RtlZeroMemory(IrpContext
, sizeof(HIDCLASS_IRP_CONTEXT
));
612 IrpContext
->OriginalIrp
= RequestIrp
;
613 IrpContext
->FileOp
= Context
;
616 // get collection description
618 CollectionDescription
= HidClassPDO_GetCollectionDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
619 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
620 ASSERT(CollectionDescription
);
623 // get report description
625 ReportDescription
= HidClassPDO_GetReportDescription(&IrpContext
->FileOp
->DeviceExtension
->Common
.DeviceDescription
,
626 IrpContext
->FileOp
->DeviceExtension
->CollectionNumber
);
627 ASSERT(ReportDescription
);
632 ASSERT(CollectionDescription
->InputLength
>= ReportDescription
->InputLength
);
634 if (Context
->StopInProgress
)
639 DPRINT1("[HIDCLASS] Stop In Progress\n");
640 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
641 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
642 return STATUS_CANCELLED
;
647 // store report length
649 IrpContext
->InputReportBufferLength
= ReportDescription
->InputLength
;
654 IrpContext
->InputReportBuffer
= ExAllocatePoolWithTag(NonPagedPool
, IrpContext
->InputReportBufferLength
, HIDCLASS_TAG
);
655 if (!IrpContext
->InputReportBuffer
)
661 ExFreePoolWithTag(IrpContext
, HIDCLASS_TAG
);
662 return STATUS_INSUFFICIENT_RESOURCES
;
666 // get stack location
668 IoStack
= IoGetNextIrpStackLocation(Irp
);
671 // init stack location
673 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
674 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= DeviceIoControlCode
;
675 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= IrpContext
->InputReportBufferLength
;
676 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
677 IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
678 Irp
->UserBuffer
= IrpContext
->InputReportBuffer
;
679 IoStack
->DeviceObject
= DeviceObject
;
685 *OutIrpContext
= IrpContext
;
690 return STATUS_SUCCESS
;
696 IN PDEVICE_OBJECT DeviceObject
,
699 PIO_STACK_LOCATION IoStack
;
700 PHIDCLASS_FILEOP_CONTEXT Context
;
704 PHIDCLASS_IRP_CONTEXT NewIrpContext
;
705 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
708 // get current stack location
710 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
713 // get device extension
715 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
716 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
721 ASSERT(IoStack
->FileObject
);
722 ASSERT(IoStack
->FileObject
->FsContext
);
727 Context
= IoStack
->FileObject
->FsContext
;
731 // FIXME support polled devices
733 ASSERT(Context
->DeviceExtension
->Common
.DriverExtension
->DevicesArePolled
== FALSE
);
735 if (Context
->StopInProgress
)
740 DPRINT1("[HIDCLASS] Stop In Progress\n");
741 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
742 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
743 return STATUS_CANCELLED
;
749 Status
= HidClass_BuildIrp(DeviceObject
,
752 IOCTL_HID_READ_REPORT
,
753 IoStack
->Parameters
.Read
.Length
,
756 if (!NT_SUCCESS(Status
))
761 DPRINT1("HidClass_BuildIrp failed with %x\n", Status
);
762 Irp
->IoStatus
.Status
= Status
;
763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
770 KeAcquireSpinLock(&Context
->Lock
, &OldLevel
);
773 // insert irp into pending list
775 InsertTailList(&Context
->ReadPendingIrpListHead
, &NewIrp
->Tail
.Overlay
.ListEntry
);
778 // set completion routine
780 IoSetCompletionRoutine(NewIrp
, HidClass_ReadCompleteIrp
, NewIrpContext
, TRUE
, TRUE
, TRUE
);
783 // make next location current
785 IoSetNextIrpStackLocation(NewIrp
);
790 KeReleaseSpinLock(&Context
->Lock
, OldLevel
);
795 IoMarkIrpPending(Irp
);
798 // let's dispatch the request
800 ASSERT(Context
->DeviceExtension
);
801 Status
= Context
->DeviceExtension
->Common
.DriverExtension
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
](Context
->DeviceExtension
->FDODeviceObject
, NewIrp
);
806 return STATUS_PENDING
;
812 IN PDEVICE_OBJECT DeviceObject
,
817 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
818 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
819 return STATUS_NOT_IMPLEMENTED
;
824 HidClass_DeviceControl(
825 IN PDEVICE_OBJECT DeviceObject
,
828 PIO_STACK_LOCATION IoStack
;
829 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
830 PHID_COLLECTION_INFORMATION CollectionInformation
;
831 PHIDP_COLLECTION_DESC CollectionDescription
;
832 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension
;
835 // get device extension
837 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
840 // only PDO are supported
842 if (CommonDeviceExtension
->IsFDO
)
847 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n");
848 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER_1
;
849 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
850 return STATUS_INVALID_PARAMETER_1
;
853 ASSERT(CommonDeviceExtension
->IsFDO
== FALSE
);
856 // get pdo device extension
858 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
861 // get stack location
863 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
865 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
867 case IOCTL_HID_GET_COLLECTION_INFORMATION
:
870 // check if output buffer is big enough
872 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(HID_COLLECTION_INFORMATION
))
875 // invalid buffer size
877 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
878 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
879 return STATUS_INVALID_BUFFER_SIZE
;
885 CollectionInformation
= Irp
->AssociatedIrp
.SystemBuffer
;
886 ASSERT(CollectionInformation
);
889 // get collection description
891 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
892 PDODeviceExtension
->CollectionNumber
);
893 ASSERT(CollectionDescription
);
896 // init result buffer
898 CollectionInformation
->DescriptorSize
= CollectionDescription
->PreparsedDataLength
;
899 CollectionInformation
->Polled
= CommonDeviceExtension
->DriverExtension
->DevicesArePolled
;
900 CollectionInformation
->VendorID
= CommonDeviceExtension
->Attributes
.VendorID
;
901 CollectionInformation
->ProductID
= CommonDeviceExtension
->Attributes
.ProductID
;
902 CollectionInformation
->VersionNumber
= CommonDeviceExtension
->Attributes
.VersionNumber
;
907 Irp
->IoStatus
.Information
= sizeof(HID_COLLECTION_INFORMATION
);
908 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
909 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
910 return STATUS_SUCCESS
;
912 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR
:
915 // get collection description
917 CollectionDescription
= HidClassPDO_GetCollectionDescription(&CommonDeviceExtension
->DeviceDescription
,
918 PDODeviceExtension
->CollectionNumber
);
919 ASSERT(CollectionDescription
);
922 // check if output buffer is big enough
924 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< CollectionDescription
->PreparsedDataLength
)
927 // invalid buffer size
929 Irp
->IoStatus
.Status
= STATUS_INVALID_BUFFER_SIZE
;
930 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
931 return STATUS_INVALID_BUFFER_SIZE
;
937 ASSERT(Irp
->UserBuffer
);
938 RtlCopyMemory(Irp
->UserBuffer
, CollectionDescription
->PreparsedData
, CollectionDescription
->PreparsedDataLength
);
943 Irp
->IoStatus
.Information
= CollectionDescription
->PreparsedDataLength
;
944 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
945 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
946 return STATUS_SUCCESS
;
950 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
951 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
952 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
953 return STATUS_NOT_IMPLEMENTED
;
960 HidClass_InternalDeviceControl(
961 IN PDEVICE_OBJECT DeviceObject
,
966 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
967 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
968 return STATUS_NOT_IMPLEMENTED
;
974 IN PDEVICE_OBJECT DeviceObject
,
977 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
978 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
980 if (CommonDeviceExtension
->IsFDO
)
982 IoCopyCurrentIrpStackLocationToNext(Irp
);
983 return HidClassFDO_DispatchRequest(DeviceObject
, Irp
);
987 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
988 PoStartNextPowerIrp(Irp
);
989 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
990 return STATUS_SUCCESS
;
997 IN PDEVICE_OBJECT DeviceObject
,
1000 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1003 // get common device extension
1005 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
1008 // check type of device object
1010 if (CommonDeviceExtension
->IsFDO
)
1015 return HidClassFDO_PnP(DeviceObject
, Irp
);
1022 return HidClassPDO_PnP(DeviceObject
, Irp
);
1028 HidClass_DispatchDefault(
1029 IN PDEVICE_OBJECT DeviceObject
,
1032 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1035 // get common device extension
1037 CommonDeviceExtension
= DeviceObject
->DeviceExtension
;
1040 // FIXME: support PDO
1042 ASSERT(CommonDeviceExtension
->IsFDO
== TRUE
);
1045 // skip current irp stack location
1047 IoSkipCurrentIrpStackLocation(Irp
);
1050 // dispatch to lower device object
1052 return IoCallDriver(CommonDeviceExtension
->HidDeviceExtension
.NextDeviceObject
, Irp
);
1058 IN PDEVICE_OBJECT DeviceObject
,
1061 PIO_STACK_LOCATION IoStack
;
1064 // get current stack location
1066 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1067 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
1070 // dispatch request based on major function
1072 switch (IoStack
->MajorFunction
)
1075 return HidClass_Create(DeviceObject
, Irp
);
1077 return HidClass_Close(DeviceObject
, Irp
);
1079 return HidClass_Read(DeviceObject
, Irp
);
1081 return HidClass_Write(DeviceObject
, Irp
);
1082 case IRP_MJ_DEVICE_CONTROL
:
1083 return HidClass_DeviceControl(DeviceObject
, Irp
);
1084 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1085 return HidClass_InternalDeviceControl(DeviceObject
, Irp
);
1087 return HidClass_Power(DeviceObject
, Irp
);
1089 return HidClass_PnP(DeviceObject
, Irp
);
1091 return HidClass_DispatchDefault(DeviceObject
, Irp
);
1097 HidRegisterMinidriver(
1098 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration
)
1101 PHIDCLASS_DRIVER_EXTENSION DriverExtension
;
1103 /* check if the version matches */
1104 if (MinidriverRegistration
->Revision
> HID_REVISION
)
1106 /* revision mismatch */
1108 return STATUS_REVISION_MISMATCH
;
1111 /* now allocate the driver object extension */
1112 Status
= IoAllocateDriverObjectExtension(MinidriverRegistration
->DriverObject
,
1113 ClientIdentificationAddress
,
1114 sizeof(HIDCLASS_DRIVER_EXTENSION
),
1115 (PVOID
*)&DriverExtension
);
1116 if (!NT_SUCCESS(Status
))
1118 /* failed to allocate driver extension */
1123 /* zero driver extension */
1124 RtlZeroMemory(DriverExtension
, sizeof(HIDCLASS_DRIVER_EXTENSION
));
1126 /* init driver extension */
1127 DriverExtension
->DriverObject
= MinidriverRegistration
->DriverObject
;
1128 DriverExtension
->DeviceExtensionSize
= MinidriverRegistration
->DeviceExtensionSize
;
1129 DriverExtension
->DevicesArePolled
= MinidriverRegistration
->DevicesArePolled
;
1130 DriverExtension
->AddDevice
= MinidriverRegistration
->DriverObject
->DriverExtension
->AddDevice
;
1131 DriverExtension
->DriverUnload
= MinidriverRegistration
->DriverObject
->DriverUnload
;
1133 /* copy driver dispatch routines */
1134 RtlCopyMemory(DriverExtension
->MajorFunction
,
1135 MinidriverRegistration
->DriverObject
->MajorFunction
,
1136 sizeof(PDRIVER_DISPATCH
) * (IRP_MJ_MAXIMUM_FUNCTION
+ 1));
1138 /* initialize lock */
1139 KeInitializeSpinLock(&DriverExtension
->Lock
);
1141 /* now replace dispatch routines */
1142 DriverExtension
->DriverObject
->DriverExtension
->AddDevice
= HidClassAddDevice
;
1143 DriverExtension
->DriverObject
->DriverUnload
= HidClassDriverUnload
;
1144 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = HidClassDispatch
;
1145 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = HidClassDispatch
;
1146 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_READ
] = HidClassDispatch
;
1147 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = HidClassDispatch
;
1148 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = HidClassDispatch
;
1149 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = HidClassDispatch
;
1150 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HidClassDispatch
;
1151 DriverExtension
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HidClassDispatch
;
1154 return STATUS_SUCCESS
;