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
;
47 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
50 /* get device extension */
51 DeviceExtension
= Context
;
53 for(Index
= 0; Index
< Length
; Index
++)
55 DPRINT("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index
, NewScanCodes
[Index
] & 0xFF);
57 /* check if this is E0 or E1 prefix */
58 if (NewScanCodes
[Index
] == (CHAR
)0xE0 || NewScanCodes
[Index
] == (CHAR
)0xE1)
60 Prefix
= NewScanCodes
[Index
];
65 RtlZeroMemory(&InputData
, sizeof(KEYBOARD_INPUT_DATA
));
67 /* use keyboard unit id */
68 InputData
.UnitId
= DeviceExtension
->KeyboardTypematic
.UnitId
;
70 if (NewScanCodes
[Index
] & 0x80)
72 /* scan codes with 0x80 flag are a key break */
73 InputData
.Flags
|= KEY_BREAK
;
76 /* set a prefix if needed */
79 InputData
.Flags
|= (Prefix
== (CHAR
)0xE0 ? KEY_E0
: KEY_E1
);
84 InputData
.MakeCode
= NewScanCodes
[Index
] & 0x7F;
86 /* dispatch scan codes */
87 KbdHid_DispatchInputData(Context
, &InputData
);
97 KbdHid_ReadCompletion(
98 IN PDEVICE_OBJECT DeviceObject
,
102 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
106 /* get device extension */
107 DeviceExtension
= Context
;
109 if (Irp
->IoStatus
.Status
== STATUS_PRIVILEGE_NOT_HELD
||
110 Irp
->IoStatus
.Status
== STATUS_DEVICE_NOT_CONNECTED
||
111 Irp
->IoStatus
.Status
== STATUS_CANCELLED
||
112 DeviceExtension
->StopReadReport
)
114 /* failed to read or should be stopped*/
115 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp
->IoStatus
.Status
);
117 /* report no longer active */
118 DeviceExtension
->ReadReportActive
= FALSE
;
120 /* request stopping of the report cycle */
121 DeviceExtension
->StopReadReport
= FALSE
;
123 /* signal completion event */
124 KeSetEvent(&DeviceExtension
->ReadCompletionEvent
, 0, 0);
125 return STATUS_MORE_PROCESSING_REQUIRED
;
129 // print out raw report
131 ASSERT(DeviceExtension
->ReportLength
>= 9);
132 DPRINT("[KBDHID] ReadCompletion %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DeviceExtension
->Report
[0], DeviceExtension
->Report
[1], DeviceExtension
->Report
[2],
133 DeviceExtension
->Report
[3], DeviceExtension
->Report
[4], DeviceExtension
->Report
[5],
134 DeviceExtension
->Report
[6], DeviceExtension
->Report
[7], DeviceExtension
->Report
[8]);
137 /* get current usages */
138 ButtonLength
= DeviceExtension
->UsageListLength
;
139 Status
= HidP_GetUsagesEx(HidP_Input
,
140 HIDP_LINK_COLLECTION_UNSPECIFIED
,
141 DeviceExtension
->CurrentUsageList
,
143 DeviceExtension
->PreparsedData
,
144 DeviceExtension
->Report
,
145 DeviceExtension
->ReportLength
);
146 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
148 /* FIXME check if needs mapping */
150 /* get usage difference */
151 Status
= HidP_UsageAndPageListDifference(DeviceExtension
->PreviousUsageList
,
152 DeviceExtension
->CurrentUsageList
,
153 DeviceExtension
->BreakUsageList
,
154 DeviceExtension
->MakeUsageList
,
155 DeviceExtension
->UsageListLength
);
156 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
158 /* replace previous usage list with current list */
159 RtlMoveMemory(DeviceExtension
->PreviousUsageList
,
160 DeviceExtension
->CurrentUsageList
,
161 sizeof(USAGE_AND_PAGE
) * DeviceExtension
->UsageListLength
);
163 /* translate break usage list */
164 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->BreakUsageList
,
165 DeviceExtension
->UsageListLength
,
167 &DeviceExtension
->ModifierState
,
168 KbdHid_InsertScanCodes
,
170 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
172 /* translate new usage list */
173 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->MakeUsageList
,
174 DeviceExtension
->UsageListLength
,
176 &DeviceExtension
->ModifierState
,
177 KbdHid_InsertScanCodes
,
179 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
182 KbdHid_InitiateRead(DeviceExtension
);
184 /* stop completion */
185 return STATUS_MORE_PROCESSING_REQUIRED
;
190 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
)
192 PIO_STACK_LOCATION IoStack
;
196 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
199 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
201 /* get next stack location */
202 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
204 /* init stack location */
205 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
206 IoStack
->Parameters
.Read
.Key
= 0;
207 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
208 IoStack
->MajorFunction
= IRP_MJ_READ
;
209 IoStack
->FileObject
= DeviceExtension
->FileObject
;
211 /* set completion routine */
212 IoSetCompletionRoutine(DeviceExtension
->Irp
, KbdHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
215 DeviceExtension
->ReadReportActive
= TRUE
;
218 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
226 KbdHid_CreateCompletion(
227 IN PDEVICE_OBJECT DeviceObject
,
231 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
232 return STATUS_MORE_PROCESSING_REQUIRED
;
239 IN PDEVICE_OBJECT DeviceObject
,
242 PIO_STACK_LOCATION IoStack
;
245 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
247 DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
249 /* get device extension */
250 DeviceExtension
= DeviceObject
->DeviceExtension
;
252 /* get stack location */
253 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
255 /* copy stack location to next */
256 IoCopyCurrentIrpStackLocationToNext(Irp
);
259 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
262 IoSetCompletionRoutine(Irp
, KbdHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
264 /* call lower driver */
265 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
266 if (Status
== STATUS_PENDING
)
268 /* request pending */
269 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
272 /* check for success */
273 if (!NT_SUCCESS(Status
))
276 Irp
->IoStatus
.Status
= Status
;
277 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
281 /* is the driver already in use */
282 if (DeviceExtension
->FileObject
== NULL
)
284 /* did the caller specify correct attributes */
285 ASSERT(IoStack
->Parameters
.Create
.SecurityContext
);
286 if (IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
)
288 /* store file object */
289 DeviceExtension
->FileObject
= IoStack
->FileObject
;
292 KeResetEvent(&DeviceExtension
->ReadCompletionEvent
);
294 /* initiating read */
295 Status
= KbdHid_InitiateRead(DeviceExtension
);
296 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status
);
297 if (Status
== STATUS_PENDING
)
299 /* report irp is pending */
300 Status
= STATUS_SUCCESS
;
305 /* complete request */
306 Irp
->IoStatus
.Status
= Status
;
307 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
315 IN PDEVICE_OBJECT DeviceObject
,
318 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
320 /* get device extension */
321 DeviceExtension
= DeviceObject
->DeviceExtension
;
323 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
325 if (DeviceExtension
->ReadReportActive
)
327 /* request stopping of the report cycle */
328 DeviceExtension
->StopReadReport
= TRUE
;
330 /* wait until the reports have been read */
331 KeWaitForSingleObject(&DeviceExtension
->ReadCompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
334 IoCancelIrp(DeviceExtension
->Irp
);
337 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
339 /* remove file object */
340 DeviceExtension
->FileObject
= NULL
;
343 IoSkipCurrentIrpStackLocation(Irp
);
345 /* pass irp to down the stack */
346 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
351 KbdHid_InternalDeviceControl(
352 IN PDEVICE_OBJECT DeviceObject
,
355 PIO_STACK_LOCATION IoStack
;
356 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
358 PKEYBOARD_ATTRIBUTES Attributes
;
360 /* get current stack location */
361 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
363 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
365 /* get device extension */
366 DeviceExtension
= DeviceObject
->DeviceExtension
;
368 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
370 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
371 /* verify output buffer length */
372 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUSE_ATTRIBUTES
))
374 /* invalid request */
375 DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
376 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
377 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
378 return STATUS_BUFFER_TOO_SMALL
;
381 /* get output buffer */
382 Attributes
= Irp
->AssociatedIrp
.SystemBuffer
;
384 /* copy attributes */
385 RtlCopyMemory(Attributes
,
386 &DeviceExtension
->Attributes
,
387 sizeof(KEYBOARD_ATTRIBUTES
));
389 /* complete request */
390 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
391 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
392 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
393 return STATUS_SUCCESS
;
395 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
396 /* verify input buffer length */
397 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
399 /* invalid request */
400 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
401 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
402 return STATUS_INVALID_PARAMETER
;
405 /* is it already connected */
406 if (DeviceExtension
->ClassService
)
408 /* already connected */
409 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
410 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
411 return STATUS_SHARING_VIOLATION
;
414 /* get connect data */
415 Data
= IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
417 /* store connect details */
418 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
419 DeviceExtension
->ClassService
= Data
->ClassService
;
421 /* completed successfully */
422 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
423 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
424 return STATUS_SUCCESS
;
426 case IOCTL_INTERNAL_KEYBOARD_DISCONNECT
:
427 /* not implemented */
428 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
429 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
430 return STATUS_NOT_IMPLEMENTED
;
432 case IOCTL_INTERNAL_KEYBOARD_ENABLE
:
434 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
435 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
436 return STATUS_NOT_SUPPORTED
;
438 case IOCTL_INTERNAL_KEYBOARD_DISABLE
:
440 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
441 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
442 return STATUS_NOT_SUPPORTED
;
444 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
445 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
447 /* invalid parameter */
448 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
449 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
450 return STATUS_INVALID_PARAMETER
;
453 /* copy indicators */
454 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
455 &DeviceExtension
->KeyboardIndicator
,
456 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
458 /* complete request */
459 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
460 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INDICATOR_PARAMETERS
);
461 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
462 return STATUS_NOT_IMPLEMENTED
;
464 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
465 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
467 /* invalid parameter */
468 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
469 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
470 return STATUS_INVALID_PARAMETER
;
473 /* copy indicators */
474 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
475 &DeviceExtension
->KeyboardTypematic
,
476 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
479 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
480 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
);
481 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
482 return STATUS_SUCCESS
;
484 case IOCTL_KEYBOARD_SET_INDICATORS
:
485 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
487 /* invalid parameter */
488 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
489 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
490 return STATUS_INVALID_PARAMETER
;
493 /* copy indicators */
494 RtlCopyMemory(&DeviceExtension
->KeyboardIndicator
,
495 Irp
->AssociatedIrp
.SystemBuffer
,
496 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
499 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
500 Irp
->IoStatus
.Information
= 0;
501 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
502 return STATUS_SUCCESS
;
504 case IOCTL_KEYBOARD_SET_TYPEMATIC
:
505 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
507 /* invalid parameter */
508 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
509 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
510 return STATUS_INVALID_PARAMETER
;
513 /* copy indicators */
514 RtlCopyMemory(&DeviceExtension
->KeyboardTypematic
,
515 Irp
->AssociatedIrp
.SystemBuffer
,
516 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
519 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
520 Irp
->IoStatus
.Information
= 0;
521 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
522 return STATUS_SUCCESS
;
524 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
525 /* not implemented */
526 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
527 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
528 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
529 return STATUS_NOT_IMPLEMENTED
;
532 /* unknown control code */
533 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
534 /* unknown request not supported */
535 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
536 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
537 return STATUS_NOT_SUPPORTED
;
542 KbdHid_DeviceControl(
543 IN PDEVICE_OBJECT DeviceObject
,
546 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
548 /* get device extension */
549 DeviceExtension
= DeviceObject
->DeviceExtension
;
551 /* skip stack location */
552 IoSkipCurrentIrpStackLocation(Irp
);
554 /* pass and forget */
555 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
561 IN PDEVICE_OBJECT DeviceObject
,
564 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
566 DeviceExtension
= DeviceObject
->DeviceExtension
;
567 PoStartNextPowerIrp(Irp
);
568 IoSkipCurrentIrpStackLocation(Irp
);
569 return PoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
574 KbdHid_SystemControl(
575 IN PDEVICE_OBJECT DeviceObject
,
578 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
580 DeviceExtension
= DeviceObject
->DeviceExtension
;
581 IoSkipCurrentIrpStackLocation(Irp
);
582 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
586 KbdHid_SubmitRequest(
587 PDEVICE_OBJECT DeviceObject
,
589 ULONG InputBufferSize
,
591 ULONG OutputBufferSize
,
595 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
598 IO_STATUS_BLOCK IoStatus
;
600 /* get device extension */
601 DeviceExtension
= DeviceObject
->DeviceExtension
;
604 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
607 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
608 DeviceExtension
->NextDeviceObject
,
619 return STATUS_INSUFFICIENT_RESOURCES
;
623 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
624 if (Status
== STATUS_PENDING
)
626 /* wait for request to complete */
627 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
628 Status
= IoStatus
.Status
;
638 IN PDEVICE_OBJECT DeviceObject
)
642 HID_COLLECTION_INFORMATION Information
;
643 PHIDP_PREPARSED_DATA PreparsedData
;
644 HIDP_CAPS Capabilities
;
645 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
646 PUSAGE_AND_PAGE Buffer
;
648 /* get device extension */
649 DeviceExtension
= DeviceObject
->DeviceExtension
;
651 /* query collection information */
652 Status
= KbdHid_SubmitRequest(DeviceObject
,
653 IOCTL_HID_GET_COLLECTION_INFORMATION
,
656 sizeof(HID_COLLECTION_INFORMATION
),
658 if (!NT_SUCCESS(Status
))
660 /* failed to query collection information */
661 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
665 /* lets allocate space for preparsed data */
666 PreparsedData
= ExAllocatePoolWithTag(NonPagedPool
, Information
.DescriptorSize
, KBDHID_TAG
);
670 DPRINT1("[KBDHID] no memory size %u\n", Information
.DescriptorSize
);
671 return STATUS_INSUFFICIENT_RESOURCES
;
674 /* now obtain the preparsed data */
675 Status
= KbdHid_SubmitRequest(DeviceObject
,
676 IOCTL_HID_GET_COLLECTION_DESCRIPTOR
,
679 Information
.DescriptorSize
,
681 if (!NT_SUCCESS(Status
))
683 /* failed to get preparsed data */
684 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
685 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
689 /* lets get the caps */
690 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
691 if (Status
!= HIDP_STATUS_SUCCESS
)
693 /* failed to get capabilities */
694 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status
);
695 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
699 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities
.Usage
, Capabilities
.UsagePage
, Capabilities
.InputReportByteLength
);
701 /* init input report */
702 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
703 ASSERT(DeviceExtension
->ReportLength
);
704 DeviceExtension
->Report
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExtension
->ReportLength
, KBDHID_TAG
);
705 ASSERT(DeviceExtension
->Report
);
706 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
709 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
,
710 DeviceExtension
->ReportLength
,
714 ASSERT(DeviceExtension
->ReportMDL
);
717 MmBuildMdlForNonPagedPool(DeviceExtension
->ReportMDL
);
719 /* get max number of buttons */
720 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_KEYBOARD
, PreparsedData
);
721 DPRINT("[KBDHID] Buttons %lu\n", Buttons
);
724 /* now allocate an array for those buttons */
725 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
, KBDHID_TAG
);
729 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
730 return STATUS_INSUFFICIENT_RESOURCES
;
732 DeviceExtension
->UsageListBuffer
= Buffer
;
734 /* init usage lists */
735 RtlZeroMemory(Buffer
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
736 DeviceExtension
->CurrentUsageList
= Buffer
;
738 DeviceExtension
->PreviousUsageList
= Buffer
;
740 DeviceExtension
->MakeUsageList
= Buffer
;
742 DeviceExtension
->BreakUsageList
= Buffer
;
745 // FIMXE: implement device hacks
748 // KeyboardTypeOverride
749 // KeyboardSubTypeOverride
750 // KeyboardNumberTotalKeysOverride
751 // KeyboardNumberFunctionKeysOverride
752 // KeyboardNumberIndicatorsOverride
754 /* store number of buttons */
755 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
757 /* store preparsed data */
758 DeviceExtension
->PreparsedData
= PreparsedData
;
760 /* completed successfully */
761 return STATUS_SUCCESS
;
766 KbdHid_StartDeviceCompletion(
767 IN PDEVICE_OBJECT DeviceObject
,
771 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
772 return STATUS_MORE_PROCESSING_REQUIRED
;
777 KbdHid_FreeResources(
778 IN PDEVICE_OBJECT DeviceObject
)
780 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
782 /* get device extension */
783 DeviceExtension
= DeviceObject
->DeviceExtension
;
786 if (DeviceExtension
->PreparsedData
)
788 ExFreePoolWithTag(DeviceExtension
->PreparsedData
, KBDHID_TAG
);
789 DeviceExtension
->PreparsedData
= NULL
;
792 if (DeviceExtension
->UsageListBuffer
)
794 ExFreePoolWithTag(DeviceExtension
->UsageListBuffer
, KBDHID_TAG
);
795 DeviceExtension
->UsageListBuffer
= NULL
;
796 DeviceExtension
->CurrentUsageList
= NULL
;
797 DeviceExtension
->PreviousUsageList
= NULL
;
798 DeviceExtension
->MakeUsageList
= NULL
;
799 DeviceExtension
->BreakUsageList
= NULL
;
802 if (DeviceExtension
->ReportMDL
)
804 IoFreeMdl(DeviceExtension
->ReportMDL
);
805 DeviceExtension
->ReportMDL
= NULL
;
808 if (DeviceExtension
->Report
)
810 ExFreePoolWithTag(DeviceExtension
->Report
, KBDHID_TAG
);
811 DeviceExtension
->Report
= NULL
;
814 return STATUS_SUCCESS
;
820 IN PDEVICE_OBJECT DeviceObject
,
823 PIO_STACK_LOCATION IoStack
;
824 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
826 /* get device extension */
827 DeviceExtension
= DeviceObject
->DeviceExtension
;
829 /* skip current stack location */
830 IoSkipCurrentIrpStackLocation(Irp
);
832 /* get next stack location */
833 IoStack
= IoGetNextIrpStackLocation(Irp
);
835 /* change request to hid flush queue request */
836 IoStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
837 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_HID_FLUSH_QUEUE
;
840 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
846 IN PDEVICE_OBJECT DeviceObject
,
849 PIO_STACK_LOCATION IoStack
;
852 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
854 /* get device extension */
855 DeviceExtension
= DeviceObject
->DeviceExtension
;
857 /* get current irp stack */
858 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
859 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack
->MinorFunction
);
861 switch (IoStack
->MinorFunction
)
863 case IRP_MN_STOP_DEVICE
:
864 case IRP_MN_SURPRISE_REMOVAL
:
866 KbdHid_FreeResources(DeviceObject
);
868 case IRP_MN_CANCEL_REMOVE_DEVICE
:
869 case IRP_MN_QUERY_STOP_DEVICE
:
870 case IRP_MN_CANCEL_STOP_DEVICE
:
871 case IRP_MN_QUERY_REMOVE_DEVICE
:
872 /* indicate success */
873 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
875 /* skip irp stack location */
876 IoSkipCurrentIrpStackLocation(Irp
);
878 /* dispatch to lower device */
879 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
881 case IRP_MN_REMOVE_DEVICE
:
882 /* FIXME synchronization */
885 IoCancelIrp(DeviceExtension
->Irp
);
888 KbdHid_FreeResources(DeviceObject
);
890 /* indicate success */
891 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
893 /* skip irp stack location */
894 IoSkipCurrentIrpStackLocation(Irp
);
896 /* dispatch to lower device */
897 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
899 IoFreeIrp(DeviceExtension
->Irp
);
900 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
901 IoDeleteDevice(DeviceObject
);
904 case IRP_MN_START_DEVICE
:
906 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
908 /* copy stack location */
909 IoCopyCurrentIrpStackLocationToNext (Irp
);
911 /* set completion routine */
912 IoSetCompletionRoutine(Irp
, KbdHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
913 Irp
->IoStatus
.Status
= 0;
916 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
917 if (Status
== STATUS_PENDING
)
919 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
920 Status
= Irp
->IoStatus
.Status
;
923 if (!NT_SUCCESS(Status
))
926 Irp
->IoStatus
.Status
= Status
;
927 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
931 /* lets start the device */
932 Status
= KbdHid_StartDevice(DeviceObject
);
933 DPRINT("KbdHid_StartDevice %x\n", Status
);
935 /* complete request */
936 Irp
->IoStatus
.Status
= Status
;
937 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
943 /* skip irp stack location */
944 IoSkipCurrentIrpStackLocation(Irp
);
946 /* dispatch to lower device */
947 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
954 IN PDRIVER_OBJECT DriverObject
,
955 IN PDEVICE_OBJECT PhysicalDeviceObject
)
958 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
959 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
962 /* create device object */
963 Status
= IoCreateDevice(DriverObject
,
964 sizeof(KBDHID_DEVICE_EXTENSION
),
966 FILE_DEVICE_KEYBOARD
,
970 if (!NT_SUCCESS(Status
))
972 /* failed to create device object */
977 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
978 if (!NextDeviceObject
)
980 /* failed to attach */
981 IoDeleteDevice(DeviceObject
);
982 return STATUS_DEVICE_NOT_CONNECTED
;
985 /* get device extension */
986 DeviceExtension
= DeviceObject
->DeviceExtension
;
989 RtlZeroMemory(DeviceExtension
, sizeof(KBDHID_DEVICE_EXTENSION
));
991 /* init device extension */
992 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
993 KeInitializeEvent(&DeviceExtension
->ReadCompletionEvent
, NotificationEvent
, FALSE
);
995 /* init keyboard attributes */
996 DeviceExtension
->Attributes
.KeyboardIdentifier
.Type
= KEYBOARD_TYPE_UNKNOWN
;
997 DeviceExtension
->Attributes
.KeyboardIdentifier
.Subtype
= MICROSOFT_KBD_101_TYPE
;
998 DeviceExtension
->Attributes
.NumberOfFunctionKeys
= MICROSOFT_KBD_FUNC
;
999 DeviceExtension
->Attributes
.NumberOfIndicators
= 3; // caps, num lock, scroll lock
1000 DeviceExtension
->Attributes
.NumberOfKeysTotal
= 101;
1001 DeviceExtension
->Attributes
.InputDataQueueLength
= 1;
1002 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Rate
= KEYBOARD_TYPEMATIC_RATE_MINIMUM
;
1003 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MINIMUM
;
1004 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Rate
= KEYBOARD_TYPEMATIC_RATE_DEFAULT
;
1005 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MAXIMUM
;
1008 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
1010 /* FIXME handle allocation error */
1011 ASSERT(DeviceExtension
->Irp
);
1013 /* set power state to D0 */
1014 State
.DeviceState
= PowerDeviceD0
;
1015 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
1017 /* init device object */
1018 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
1019 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1021 /* completed successfully */
1022 return STATUS_SUCCESS
;
1028 IN PDRIVER_OBJECT DriverObject
)
1037 IN PDRIVER_OBJECT DriverObject
,
1038 IN PUNICODE_STRING RegPath
)
1040 /* initialize driver object */
1041 DriverObject
->DriverUnload
= KbdHid_Unload
;
1042 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
1043 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdHid_Create
;
1044 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdHid_Close
;
1045 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = KbdHid_Flush
;
1046 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdHid_DeviceControl
;
1047 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = KbdHid_InternalDeviceControl
;
1048 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KbdHid_Power
;
1049 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KbdHid_Pnp
;
1050 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KbdHid_SystemControl
;
1051 DriverObject
->DriverUnload
= KbdHid_Unload
;
1052 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
1055 return STATUS_SUCCESS
;