2 * PROJECT: ReactOS HID Stack
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/hid/kbdhid/kbdhid.c
5 * PURPOSE: Keyboard HID Driver
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 KbdHid_DispatchInputData(
15 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
,
16 IN PKEYBOARD_INPUT_DATA InputData
)
19 ULONG InputDataConsumed
;
21 if (!DeviceExtension
->ClassService
)
25 ASSERT(DeviceExtension
->ClassService
);
26 ASSERT(DeviceExtension
->ClassDeviceObject
);
29 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
31 /* dispatch input data */
32 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ClassService
)(DeviceExtension
->ClassDeviceObject
, InputData
, InputData
+ 1, &InputDataConsumed
);
34 /* lower irql to previous level */
40 KbdHid_InsertScanCodes(
42 IN PCHAR NewScanCodes
,
45 //KEYBOARD_INPUT_DATA InputData;
48 for(Index
= 0; Index
< Length
; Index
++)
50 DPRINT1("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index
, NewScanCodes
[Index
] & 0xFF);
52 // TODO: set up input data
54 //KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
66 KbdHid_ReadCompletion(
67 IN PDEVICE_OBJECT DeviceObject
,
71 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
75 /* get device extension */
76 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)Context
;
78 if (Irp
->IoStatus
.Status
== STATUS_PRIVILEGE_NOT_HELD
||
79 Irp
->IoStatus
.Status
== STATUS_DEVICE_NOT_CONNECTED
||
80 Irp
->IoStatus
.Status
== STATUS_CANCELLED
||
81 DeviceExtension
->StopReadReport
)
83 /* failed to read or should be stopped*/
84 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp
->IoStatus
.Status
);
86 /* report no longer active */
87 DeviceExtension
->ReadReportActive
= FALSE
;
89 /* request stopping of the report cycle */
90 DeviceExtension
->StopReadReport
= FALSE
;
92 /* signal completion event */
93 KeSetEvent(&DeviceExtension
->ReadCompletionEvent
, 0, 0);
94 return STATUS_MORE_PROCESSING_REQUIRED
;
97 /* get current usages */
98 ButtonLength
= DeviceExtension
->UsageListLength
;
99 Status
= HidP_GetUsagesEx(HidP_Input
, HIDP_LINK_COLLECTION_UNSPECIFIED
, DeviceExtension
->CurrentUsageList
, &ButtonLength
, DeviceExtension
->PreparsedData
, DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
100 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
102 /* FIXME check if needs mapping */
104 /* get usage difference */
105 Status
= HidP_UsageAndPageListDifference(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, DeviceExtension
->BreakUsageList
, DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
);
106 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
108 /* replace previous usage list with current list */
109 RtlMoveMemory(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, sizeof(USAGE_AND_PAGE
) * DeviceExtension
->UsageListLength
);
111 /* translate break usage list */
112 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->BreakUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Break
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
113 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
115 /* translate new usage list */
116 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Make
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
117 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
120 KbdHid_InitiateRead(DeviceExtension
);
122 /* stop completion */
123 return STATUS_MORE_PROCESSING_REQUIRED
;
128 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
)
130 PIO_STACK_LOCATION IoStack
;
134 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
137 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
139 /* get next stack location */
140 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
142 /* init stack location */
143 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
144 IoStack
->Parameters
.Read
.Key
= 0;
145 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
146 IoStack
->MajorFunction
= IRP_MJ_READ
;
147 IoStack
->FileObject
= DeviceExtension
->FileObject
;
149 /* set completion routine */
150 IoSetCompletionRoutine(DeviceExtension
->Irp
, KbdHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
153 DeviceExtension
->ReadReportActive
= TRUE
;
156 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
164 KbdHid_CreateCompletion(
165 IN PDEVICE_OBJECT DeviceObject
,
169 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
170 return STATUS_MORE_PROCESSING_REQUIRED
;
177 IN PDEVICE_OBJECT DeviceObject
,
180 PIO_STACK_LOCATION IoStack
;
183 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
185 DPRINT1("[KBDHID]: IRP_MJ_CREATE\n");
187 /* get device extension */
188 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
190 /* get stack location */
191 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
193 /* copy stack location to next */
194 IoCopyCurrentIrpStackLocationToNext(Irp
);
197 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
200 IoSetCompletionRoutine(Irp
, KbdHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
202 /* call lower driver */
203 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
204 if (Status
== STATUS_PENDING
)
206 /* request pending */
207 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
210 /* check for success */
211 if (!NT_SUCCESS(Status
))
214 Irp
->IoStatus
.Status
= Status
;
215 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
219 /* is the driver already in use */
220 if (DeviceExtension
->FileObject
== NULL
)
222 /* did the caller specify correct attributes */
223 ASSERT(IoStack
->Parameters
.Create
.SecurityContext
);
224 if (IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
)
226 /* store file object */
227 DeviceExtension
->FileObject
= IoStack
->FileObject
;
230 KeResetEvent(&DeviceExtension
->ReadCompletionEvent
);
232 /* initiating read */
233 Status
= KbdHid_InitiateRead(DeviceExtension
);
234 DPRINT1("[KBDHID] KbdHid_InitiateRead: status %x\n", Status
);
235 if (Status
== STATUS_PENDING
)
237 /* report irp is pending */
238 Status
= STATUS_SUCCESS
;
243 /* complete request */
244 Irp
->IoStatus
.Status
= Status
;
245 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
253 IN PDEVICE_OBJECT DeviceObject
,
256 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
258 /* get device extension */
259 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
261 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
263 if (DeviceExtension
->ReadReportActive
)
265 /* request stopping of the report cycle */
266 DeviceExtension
->StopReadReport
= TRUE
;
268 /* wait until the reports have been read */
269 KeWaitForSingleObject(&DeviceExtension
->ReadCompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
272 IoCancelIrp(DeviceExtension
->Irp
);
275 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
277 /* remove file object */
278 DeviceExtension
->FileObject
= NULL
;
281 IoSkipCurrentIrpStackLocation(Irp
);
283 /* pass irp to down the stack */
284 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
289 KbdHid_InternalDeviceControl(
290 IN PDEVICE_OBJECT DeviceObject
,
293 PIO_STACK_LOCATION IoStack
;
294 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
296 PKEYBOARD_ATTRIBUTES Attributes
;
298 /* get current stack location */
299 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
301 DPRINT1("[KBDHID] InternalDeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
303 /* get device extension */
304 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
306 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_ATTRIBUTES
)
308 /* verify output buffer length */
309 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUSE_ATTRIBUTES
))
311 /* invalid request */
312 DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
313 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
314 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
315 return STATUS_BUFFER_TOO_SMALL
;
318 /* get output buffer */
319 Attributes
= (PKEYBOARD_ATTRIBUTES
)Irp
->AssociatedIrp
.SystemBuffer
;
321 /* copy attributes */
322 RtlCopyMemory(Attributes
, &DeviceExtension
->Attributes
, sizeof(KEYBOARD_ATTRIBUTES
));
324 /* complete request */
325 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
326 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
327 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
328 return STATUS_SUCCESS
;
330 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_CONNECT
)
332 /* verify input buffer length */
333 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
335 /* invalid request */
336 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
337 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
338 return STATUS_INVALID_PARAMETER
;
341 /* is it already connected */
342 if (DeviceExtension
->ClassService
)
344 /* already connected */
345 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
346 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
347 return STATUS_SHARING_VIOLATION
;
350 /* get connect data */
351 Data
= (PCONNECT_DATA
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
353 /* store connect details */
354 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
355 DeviceExtension
->ClassService
= Data
->ClassService
;
357 /* completed successfully */
358 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
359 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
360 return STATUS_SUCCESS
;
362 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISCONNECT
)
364 /* not implemented */
365 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
366 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
367 return STATUS_NOT_IMPLEMENTED
;
369 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_ENABLE
)
372 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
373 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
374 return STATUS_NOT_SUPPORTED
;
376 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISABLE
)
379 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
380 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
381 return STATUS_NOT_SUPPORTED
;
383 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATORS
)
385 /* not implemented */
386 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATORS not implemented\n");
387 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
388 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
389 return STATUS_NOT_IMPLEMENTED
;
391 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_TYPEMATIC
)
393 /* not implemented */
394 DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n");
395 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
396 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
397 return STATUS_NOT_IMPLEMENTED
;
399 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_INDICATORS
)
401 /* not implemented */
402 DPRINT1("IOCTL_KEYBOARD_SET_INDICATORS not implemented\n");
403 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
404 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
405 return STATUS_NOT_IMPLEMENTED
;
407 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_TYPEMATIC
)
409 /* not implemented */
410 DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n");
411 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
412 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
413 return STATUS_NOT_IMPLEMENTED
;
415 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
)
417 /* not implemented */
418 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
419 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
420 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
421 return STATUS_NOT_IMPLEMENTED
;
424 /* unknown control code */
425 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
426 /* unknown request not supported */
427 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
428 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
429 return STATUS_NOT_SUPPORTED
;
434 KbdHid_DeviceControl(
435 IN PDEVICE_OBJECT DeviceObject
,
438 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
440 /* get device extension */
441 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
443 /* skip stack location */
444 IoSkipCurrentIrpStackLocation(Irp
);
446 /* pass and forget */
447 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
453 IN PDEVICE_OBJECT DeviceObject
,
457 return STATUS_NOT_IMPLEMENTED
;
461 KbdHid_SubmitRequest(
462 PDEVICE_OBJECT DeviceObject
,
464 ULONG InputBufferSize
,
466 ULONG OutputBufferSize
,
470 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
473 IO_STATUS_BLOCK IoStatus
;
475 /* get device extension */
476 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
479 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
482 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceExtension
->NextDeviceObject
, InputBuffer
, InputBufferSize
, OutputBuffer
, OutputBufferSize
, FALSE
, &Event
, &IoStatus
);
486 return STATUS_INSUFFICIENT_RESOURCES
;
490 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
491 if (Status
== STATUS_PENDING
)
493 /* wait for request to complete */
494 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
495 Status
= IoStatus
.Status
;
505 IN PDEVICE_OBJECT DeviceObject
)
509 HID_COLLECTION_INFORMATION Information
;
510 PHIDP_PREPARSED_DATA PreparsedData
;
511 HIDP_CAPS Capabilities
;
512 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
513 PUSAGE_AND_PAGE Buffer
;
515 /* get device extension */
516 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
518 /* query collection information */
519 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_INFORMATION
, 0, NULL
, sizeof(HID_COLLECTION_INFORMATION
), &Information
);
520 if (!NT_SUCCESS(Status
))
522 /* failed to query collection information */
523 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
527 /* lets allocate space for preparsed data */
528 PreparsedData
= (PHIDP_PREPARSED_DATA
)ExAllocatePool(NonPagedPool
, Information
.DescriptorSize
);
532 DPRINT1("[KBDHID] no memory size %u\n", Information
.DescriptorSize
);
533 return STATUS_INSUFFICIENT_RESOURCES
;
536 /* now obtain the preparsed data */
537 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_DESCRIPTOR
, 0, NULL
, Information
.DescriptorSize
, PreparsedData
);
538 if (!NT_SUCCESS(Status
))
540 /* failed to get preparsed data */
541 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
542 ExFreePool(PreparsedData
);
546 /* lets get the caps */
547 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
548 if (Status
!= HIDP_STATUS_SUCCESS
)
550 /* failed to get capabilities */
551 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status
);
552 ExFreePool(PreparsedData
);
556 DPRINT1("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities
.Usage
, Capabilities
.UsagePage
, Capabilities
.InputReportByteLength
);
558 /* init input report*/
559 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
560 ASSERT(DeviceExtension
->ReportLength
);
561 DeviceExtension
->Report
= (PCHAR
)ExAllocatePool(NonPagedPool
, DeviceExtension
->ReportLength
);
562 ASSERT(DeviceExtension
->Report
);
563 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
566 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
, DeviceExtension
->ReportLength
, FALSE
, FALSE
, NULL
);
567 ASSERT(DeviceExtension
->ReportMDL
);
570 MmBuildMdlForNonPagedPool(DeviceExtension
->ReportMDL
);
572 /* get max number of buttons */
573 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_KEYBOARD
, PreparsedData
);
574 DPRINT1("[KBDHID] Buttons %lu\n", Buttons
);
577 /* now allocate an array for those buttons */
578 Buffer
= (PUSAGE_AND_PAGE
)ExAllocatePool(NonPagedPool
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
582 ExFreePool(PreparsedData
);
583 return STATUS_INSUFFICIENT_RESOURCES
;
586 /* init usage lists */
587 RtlZeroMemory(Buffer
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
588 DeviceExtension
->CurrentUsageList
= Buffer
;
590 DeviceExtension
->PreviousUsageList
= Buffer
;
592 DeviceExtension
->MakeUsageList
= Buffer
;
594 DeviceExtension
->BreakUsageList
= Buffer
;
597 // FIMXE: implement device hacks
600 // KeyboardTypeOverride
601 // KeyboardSubTypeOverride
602 // KeyboardNumberTotalKeysOverride
603 // KeyboardNumberFunctionKeysOverride
604 // KeyboardNumberIndicatorsOverride
606 /* store number of buttons */
607 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
609 /* store preparsed data */
610 DeviceExtension
->PreparsedData
= PreparsedData
;
612 /* completed successfully */
613 return STATUS_SUCCESS
;
618 KbdHid_StartDeviceCompletion(
619 IN PDEVICE_OBJECT DeviceObject
,
623 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
624 return STATUS_MORE_PROCESSING_REQUIRED
;
630 IN PDEVICE_OBJECT DeviceObject
,
633 PIO_STACK_LOCATION IoStack
;
634 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
636 /* get device extension */
637 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
639 /* skip current stack location */
640 IoSkipCurrentIrpStackLocation(Irp
);
642 /* get next stack location */
643 IoStack
= IoGetNextIrpStackLocation(Irp
);
645 /* change request to hid flush queue request */
646 IoStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
647 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_HID_FLUSH_QUEUE
;
650 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
656 IN PDEVICE_OBJECT DeviceObject
,
659 PIO_STACK_LOCATION IoStack
;
662 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
664 /* get device extension */
665 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
667 /* get current irp stack */
668 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
669 DPRINT1("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack
->MinorFunction
);
671 if (IoStack
->MinorFunction
== IRP_MN_STOP_DEVICE
|| IoStack
->MinorFunction
== IRP_MN_CANCEL_REMOVE_DEVICE
|| IoStack
->MinorFunction
== IRP_MN_QUERY_STOP_DEVICE
|| IoStack
->MinorFunction
== IRP_MN_CANCEL_STOP_DEVICE
)
673 /* indicate success */
674 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
676 /* skip irp stack location */
677 IoSkipCurrentIrpStackLocation(Irp
);
679 /* dispatch to lower device */
680 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
682 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
684 /* FIXME synchronization */
687 IoCancelIrp(DeviceExtension
->Irp
);
689 /* indicate success */
690 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
692 /* skip irp stack location */
693 IoSkipCurrentIrpStackLocation(Irp
);
695 /* dispatch to lower device */
696 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
698 IoFreeIrp(DeviceExtension
->Irp
);
699 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
700 IoDeleteDevice(DeviceObject
);
703 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
706 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
708 /* copy stack location */
709 IoCopyCurrentIrpStackLocationToNext (Irp
);
711 /* set completion routine */
712 IoSetCompletionRoutine(Irp
, KbdHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
713 Irp
->IoStatus
.Status
= 0;
716 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
717 if (Status
== STATUS_PENDING
)
719 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
720 Status
= Irp
->IoStatus
.Status
;
723 if (!NT_SUCCESS(Status
))
726 Irp
->IoStatus
.Status
= Status
;
727 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
731 /* lets start the device */
732 Status
= KbdHid_StartDevice(DeviceObject
);
733 DPRINT1("KbdHid_StartDevice %x\n", Status
);
735 /* complete request */
736 Irp
->IoStatus
.Status
= Status
;
737 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
744 /* skip irp stack location */
745 IoSkipCurrentIrpStackLocation(Irp
);
747 /* dispatch to lower device */
748 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
755 IN PDRIVER_OBJECT DriverObject
,
756 IN PDEVICE_OBJECT PhysicalDeviceObject
)
759 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
760 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
763 /* create device object */
764 Status
= IoCreateDevice(DriverObject
, sizeof(KBDHID_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KEYBOARD
, 0, FALSE
, &DeviceObject
);
765 if (!NT_SUCCESS(Status
))
767 /* failed to create device object */
772 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
773 if (!NextDeviceObject
)
775 /* failed to attach */
776 IoDeleteDevice(DeviceObject
);
777 return STATUS_DEVICE_NOT_CONNECTED
;
780 /* get device extension */
781 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
784 RtlZeroMemory(DeviceExtension
, sizeof(KBDHID_DEVICE_EXTENSION
));
786 /* init device extension */
787 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
788 KeInitializeEvent(&DeviceExtension
->ReadCompletionEvent
, NotificationEvent
, FALSE
);
790 /* init keyboard attributes */
791 DeviceExtension
->Attributes
.KeyboardIdentifier
.Type
= KEYBOARD_TYPE_UNKNOWN
;
792 DeviceExtension
->Attributes
.KeyboardIdentifier
.Subtype
= MICROSOFT_KBD_101_TYPE
;
793 DeviceExtension
->Attributes
.NumberOfFunctionKeys
= MICROSOFT_KBD_FUNC
;
794 DeviceExtension
->Attributes
.NumberOfIndicators
= 3; // caps, num lock, scroll lock
795 DeviceExtension
->Attributes
.NumberOfKeysTotal
= 101;
796 DeviceExtension
->Attributes
.InputDataQueueLength
= 1;
797 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Rate
= KEYBOARD_TYPEMATIC_RATE_MINIMUM
;
798 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MINIMUM
;
799 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Rate
= KEYBOARD_TYPEMATIC_RATE_DEFAULT
;
800 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MAXIMUM
;
803 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
805 /* FIXME handle allocation error */
806 ASSERT(DeviceExtension
->Irp
);
808 /* set power state to D0 */
809 State
.DeviceState
= PowerDeviceD0
;
810 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
812 /* init device object */
813 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
814 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
816 /* completed successfully */
817 return STATUS_SUCCESS
;
823 IN PDRIVER_OBJECT DriverObject
)
832 IN PDRIVER_OBJECT DriverObject
,
833 IN PUNICODE_STRING RegPath
)
835 /* initialize driver object */
836 DriverObject
->DriverUnload
= KbdHid_Unload
;
837 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
838 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdHid_Create
;
839 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdHid_Close
;
840 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = KbdHid_Flush
;
841 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdHid_DeviceControl
;
842 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = KbdHid_InternalDeviceControl
;
843 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KbdHid_Power
;
844 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KbdHid_Pnp
;
845 DriverObject
->DriverUnload
= KbdHid_Unload
;
846 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
849 return STATUS_SUCCESS
;