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)
13 /* This structure starts with the same layout as KEYBOARD_INDICATOR_TRANSLATION */
14 typedef struct _LOCAL_KEYBOARD_INDICATOR_TRANSLATION
{
15 USHORT NumberOfIndicatorKeys
;
16 INDICATOR_LIST IndicatorList
[3];
17 } LOCAL_KEYBOARD_INDICATOR_TRANSLATION
, *PLOCAL_KEYBOARD_INDICATOR_TRANSLATION
;
19 static LOCAL_KEYBOARD_INDICATOR_TRANSLATION IndicatorTranslation
= { 3, {
20 {0x3A, KEYBOARD_CAPS_LOCK_ON
},
21 {0x45, KEYBOARD_NUM_LOCK_ON
},
22 {0x46, KEYBOARD_SCROLL_LOCK_ON
}}};
26 KbdHid_DispatchInputData(
27 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
,
28 IN PKEYBOARD_INPUT_DATA InputData
)
31 ULONG InputDataConsumed
;
33 if (!DeviceExtension
->ClassService
)
37 ASSERT(DeviceExtension
->ClassService
);
38 ASSERT(DeviceExtension
->ClassDeviceObject
);
41 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
43 /* dispatch input data */
44 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ClassService
)(DeviceExtension
->ClassDeviceObject
, InputData
, InputData
+ 1, &InputDataConsumed
);
46 /* lower irql to previous level */
52 KbdHid_InsertScanCodes(
54 IN PCHAR NewScanCodes
,
57 KEYBOARD_INPUT_DATA InputData
;
59 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
62 /* get device extension */
63 DeviceExtension
= Context
;
65 for(Index
= 0; Index
< Length
; Index
++)
67 DPRINT("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index
, NewScanCodes
[Index
] & 0xFF);
69 /* check if this is E0 or E1 prefix */
70 if (NewScanCodes
[Index
] == (CHAR
)0xE0 || NewScanCodes
[Index
] == (CHAR
)0xE1)
72 Prefix
= NewScanCodes
[Index
];
77 RtlZeroMemory(&InputData
, sizeof(KEYBOARD_INPUT_DATA
));
79 /* use keyboard unit id */
80 InputData
.UnitId
= DeviceExtension
->KeyboardTypematic
.UnitId
;
82 if (NewScanCodes
[Index
] & 0x80)
84 /* scan codes with 0x80 flag are a key break */
85 InputData
.Flags
|= KEY_BREAK
;
88 /* set a prefix if needed */
91 InputData
.Flags
|= (Prefix
== (CHAR
)0xE0 ? KEY_E0
: KEY_E1
);
96 InputData
.MakeCode
= NewScanCodes
[Index
] & 0x7F;
98 /* dispatch scan codes */
99 KbdHid_DispatchInputData(Context
, &InputData
);
109 KbdHid_ReadCompletion(
110 IN PDEVICE_OBJECT DeviceObject
,
114 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
118 /* get device extension */
119 DeviceExtension
= Context
;
121 if (Irp
->IoStatus
.Status
== STATUS_PRIVILEGE_NOT_HELD
||
122 Irp
->IoStatus
.Status
== STATUS_DEVICE_NOT_CONNECTED
||
123 Irp
->IoStatus
.Status
== STATUS_CANCELLED
||
124 DeviceExtension
->StopReadReport
)
126 /* failed to read or should be stopped*/
127 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp
->IoStatus
.Status
);
129 /* report no longer active */
130 DeviceExtension
->ReadReportActive
= FALSE
;
132 /* request stopping of the report cycle */
133 DeviceExtension
->StopReadReport
= FALSE
;
135 /* signal completion event */
136 KeSetEvent(&DeviceExtension
->ReadCompletionEvent
, 0, 0);
137 return STATUS_MORE_PROCESSING_REQUIRED
;
141 // print out raw report
143 ASSERT(DeviceExtension
->ReportLength
>= 9);
144 DPRINT("[KBDHID] ReadCompletion %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DeviceExtension
->Report
[0], DeviceExtension
->Report
[1], DeviceExtension
->Report
[2],
145 DeviceExtension
->Report
[3], DeviceExtension
->Report
[4], DeviceExtension
->Report
[5],
146 DeviceExtension
->Report
[6], DeviceExtension
->Report
[7], DeviceExtension
->Report
[8]);
149 /* get current usages */
150 ButtonLength
= DeviceExtension
->UsageListLength
;
151 Status
= HidP_GetUsagesEx(HidP_Input
,
152 HIDP_LINK_COLLECTION_UNSPECIFIED
,
153 DeviceExtension
->CurrentUsageList
,
155 DeviceExtension
->PreparsedData
,
156 DeviceExtension
->Report
,
157 DeviceExtension
->ReportLength
);
158 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
160 /* FIXME check if needs mapping */
162 /* get usage difference */
163 Status
= HidP_UsageAndPageListDifference(DeviceExtension
->PreviousUsageList
,
164 DeviceExtension
->CurrentUsageList
,
165 DeviceExtension
->BreakUsageList
,
166 DeviceExtension
->MakeUsageList
,
167 DeviceExtension
->UsageListLength
);
168 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
170 /* replace previous usage list with current list */
171 RtlMoveMemory(DeviceExtension
->PreviousUsageList
,
172 DeviceExtension
->CurrentUsageList
,
173 sizeof(USAGE_AND_PAGE
) * DeviceExtension
->UsageListLength
);
175 /* translate break usage list */
176 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->BreakUsageList
,
177 DeviceExtension
->UsageListLength
,
179 &DeviceExtension
->ModifierState
,
180 KbdHid_InsertScanCodes
,
182 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
184 /* translate new usage list */
185 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->MakeUsageList
,
186 DeviceExtension
->UsageListLength
,
188 &DeviceExtension
->ModifierState
,
189 KbdHid_InsertScanCodes
,
191 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
194 KbdHid_InitiateRead(DeviceExtension
);
196 /* stop completion */
197 return STATUS_MORE_PROCESSING_REQUIRED
;
202 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
)
204 PIO_STACK_LOCATION IoStack
;
208 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
211 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
213 /* get next stack location */
214 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
216 /* init stack location */
217 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
218 IoStack
->Parameters
.Read
.Key
= 0;
219 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
220 IoStack
->MajorFunction
= IRP_MJ_READ
;
221 IoStack
->FileObject
= DeviceExtension
->FileObject
;
223 /* set completion routine */
224 IoSetCompletionRoutine(DeviceExtension
->Irp
, KbdHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
227 DeviceExtension
->ReadReportActive
= TRUE
;
230 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
238 KbdHid_CreateCompletion(
239 IN PDEVICE_OBJECT DeviceObject
,
243 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
244 return STATUS_MORE_PROCESSING_REQUIRED
;
251 IN PDEVICE_OBJECT DeviceObject
,
254 PIO_STACK_LOCATION IoStack
;
257 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
259 DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
261 /* get device extension */
262 DeviceExtension
= DeviceObject
->DeviceExtension
;
264 /* get stack location */
265 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
267 /* copy stack location to next */
268 IoCopyCurrentIrpStackLocationToNext(Irp
);
271 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
274 IoSetCompletionRoutine(Irp
, KbdHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
276 /* call lower driver */
277 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
278 if (Status
== STATUS_PENDING
)
280 /* request pending */
281 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
284 /* check for success */
285 if (!NT_SUCCESS(Status
))
288 Irp
->IoStatus
.Status
= Status
;
289 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
293 /* is the driver already in use */
294 if (DeviceExtension
->FileObject
== NULL
)
296 /* did the caller specify correct attributes */
297 ASSERT(IoStack
->Parameters
.Create
.SecurityContext
);
298 if (IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
)
300 /* store file object */
301 DeviceExtension
->FileObject
= IoStack
->FileObject
;
304 KeClearEvent(&DeviceExtension
->ReadCompletionEvent
);
306 /* initiating read */
307 Status
= KbdHid_InitiateRead(DeviceExtension
);
308 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status
);
309 if (Status
== STATUS_PENDING
)
311 /* report irp is pending */
312 Status
= STATUS_SUCCESS
;
317 /* complete request */
318 Irp
->IoStatus
.Status
= Status
;
319 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
327 IN PDEVICE_OBJECT DeviceObject
,
330 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
332 /* get device extension */
333 DeviceExtension
= DeviceObject
->DeviceExtension
;
335 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
337 if (DeviceExtension
->ReadReportActive
)
339 /* request stopping of the report cycle */
340 DeviceExtension
->StopReadReport
= TRUE
;
342 /* wait until the reports have been read */
343 KeWaitForSingleObject(&DeviceExtension
->ReadCompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
346 IoCancelIrp(DeviceExtension
->Irp
);
349 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
351 /* remove file object */
352 DeviceExtension
->FileObject
= NULL
;
355 IoSkipCurrentIrpStackLocation(Irp
);
357 /* pass irp to down the stack */
358 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
363 KbdHid_InternalDeviceControl(
364 IN PDEVICE_OBJECT DeviceObject
,
367 PIO_STACK_LOCATION IoStack
;
368 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
370 PKEYBOARD_ATTRIBUTES Attributes
;
372 /* get current stack location */
373 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
375 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
377 /* get device extension */
378 DeviceExtension
= DeviceObject
->DeviceExtension
;
380 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
382 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
383 /* verify output buffer length */
384 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_ATTRIBUTES
))
386 /* invalid request */
387 DPRINT1("[KBDHID] IOCTL_KEYBOARD_QUERY_ATTRIBUTES Buffer too small\n");
388 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
389 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
390 return STATUS_BUFFER_TOO_SMALL
;
393 /* get output buffer */
394 Attributes
= Irp
->AssociatedIrp
.SystemBuffer
;
396 /* copy attributes */
397 RtlCopyMemory(Attributes
,
398 &DeviceExtension
->Attributes
,
399 sizeof(KEYBOARD_ATTRIBUTES
));
401 /* complete request */
402 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_ATTRIBUTES
);
403 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
404 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
405 return STATUS_SUCCESS
;
407 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
408 /* verify input buffer length */
409 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
411 /* invalid request */
412 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
413 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
414 return STATUS_INVALID_PARAMETER
;
417 /* is it already connected */
418 if (DeviceExtension
->ClassService
)
420 /* already connected */
421 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
422 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
423 return STATUS_SHARING_VIOLATION
;
426 /* get connect data */
427 Data
= IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
429 /* store connect details */
430 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
431 DeviceExtension
->ClassService
= Data
->ClassService
;
433 /* completed successfully */
434 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
435 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
436 return STATUS_SUCCESS
;
438 case IOCTL_INTERNAL_KEYBOARD_DISCONNECT
:
439 /* not implemented */
440 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
441 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
442 return STATUS_NOT_IMPLEMENTED
;
444 case IOCTL_INTERNAL_KEYBOARD_ENABLE
:
446 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
447 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
448 return STATUS_NOT_SUPPORTED
;
450 case IOCTL_INTERNAL_KEYBOARD_DISABLE
:
452 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
453 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
454 return STATUS_NOT_SUPPORTED
;
456 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
457 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
459 /* buffer too small */
460 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
461 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
462 return STATUS_BUFFER_TOO_SMALL
;
465 /* copy indicators */
466 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
467 &DeviceExtension
->KeyboardIndicator
,
468 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
470 /* complete request */
471 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
472 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INDICATOR_PARAMETERS
);
473 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
474 return STATUS_NOT_IMPLEMENTED
;
476 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
477 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
479 /* buffer too small */
480 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
481 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
482 return STATUS_BUFFER_TOO_SMALL
;
485 /* copy indicators */
486 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
487 &DeviceExtension
->KeyboardTypematic
,
488 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
491 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
492 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
);
493 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
494 return STATUS_SUCCESS
;
496 case IOCTL_KEYBOARD_SET_INDICATORS
:
497 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
499 /* invalid parameter */
500 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
501 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
502 return STATUS_INVALID_PARAMETER
;
505 /* copy indicators */
506 RtlCopyMemory(&DeviceExtension
->KeyboardIndicator
,
507 Irp
->AssociatedIrp
.SystemBuffer
,
508 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
511 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
512 Irp
->IoStatus
.Information
= 0;
513 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
514 return STATUS_SUCCESS
;
516 case IOCTL_KEYBOARD_SET_TYPEMATIC
:
517 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
519 /* invalid parameter */
520 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
521 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
522 return STATUS_INVALID_PARAMETER
;
525 /* copy indicators */
526 RtlCopyMemory(&DeviceExtension
->KeyboardTypematic
,
527 Irp
->AssociatedIrp
.SystemBuffer
,
528 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
531 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
532 Irp
->IoStatus
.Information
= 0;
533 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
534 return STATUS_SUCCESS
;
536 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
537 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
))
539 /* buffer too small */
540 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
541 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
542 return STATUS_INVALID_PARAMETER
;
545 /* copy translations */
546 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
547 &IndicatorTranslation
,
548 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
));
551 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
552 Irp
->IoStatus
.Information
= sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
);
553 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
554 return STATUS_SUCCESS
;
557 /* unknown control code */
558 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
559 /* unknown request not supported */
560 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
561 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
562 return STATUS_NOT_SUPPORTED
;
567 KbdHid_DeviceControl(
568 IN PDEVICE_OBJECT DeviceObject
,
571 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
573 /* get device extension */
574 DeviceExtension
= DeviceObject
->DeviceExtension
;
576 /* skip stack location */
577 IoSkipCurrentIrpStackLocation(Irp
);
579 /* pass and forget */
580 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
586 IN PDEVICE_OBJECT DeviceObject
,
589 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
591 DeviceExtension
= DeviceObject
->DeviceExtension
;
592 PoStartNextPowerIrp(Irp
);
593 IoSkipCurrentIrpStackLocation(Irp
);
594 return PoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
599 KbdHid_SystemControl(
600 IN PDEVICE_OBJECT DeviceObject
,
603 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
605 DeviceExtension
= DeviceObject
->DeviceExtension
;
606 IoSkipCurrentIrpStackLocation(Irp
);
607 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
611 KbdHid_SubmitRequest(
612 PDEVICE_OBJECT DeviceObject
,
614 ULONG InputBufferSize
,
616 ULONG OutputBufferSize
,
620 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
623 IO_STATUS_BLOCK IoStatus
;
625 /* get device extension */
626 DeviceExtension
= DeviceObject
->DeviceExtension
;
629 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
632 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
633 DeviceExtension
->NextDeviceObject
,
644 return STATUS_INSUFFICIENT_RESOURCES
;
648 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
649 if (Status
== STATUS_PENDING
)
651 /* wait for request to complete */
652 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
653 Status
= IoStatus
.Status
;
663 IN PDEVICE_OBJECT DeviceObject
)
667 HID_COLLECTION_INFORMATION Information
;
668 PHIDP_PREPARSED_DATA PreparsedData
;
669 HIDP_CAPS Capabilities
;
670 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
671 PUSAGE_AND_PAGE Buffer
;
673 /* get device extension */
674 DeviceExtension
= DeviceObject
->DeviceExtension
;
676 /* query collection information */
677 Status
= KbdHid_SubmitRequest(DeviceObject
,
678 IOCTL_HID_GET_COLLECTION_INFORMATION
,
681 sizeof(HID_COLLECTION_INFORMATION
),
683 if (!NT_SUCCESS(Status
))
685 /* failed to query collection information */
686 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
690 /* lets allocate space for preparsed data */
691 PreparsedData
= ExAllocatePoolWithTag(NonPagedPool
, Information
.DescriptorSize
, KBDHID_TAG
);
695 DPRINT1("[KBDHID] no memory size %u\n", Information
.DescriptorSize
);
696 return STATUS_INSUFFICIENT_RESOURCES
;
699 /* now obtain the preparsed data */
700 Status
= KbdHid_SubmitRequest(DeviceObject
,
701 IOCTL_HID_GET_COLLECTION_DESCRIPTOR
,
704 Information
.DescriptorSize
,
706 if (!NT_SUCCESS(Status
))
708 /* failed to get preparsed data */
709 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
710 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
714 /* lets get the caps */
715 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
716 if (Status
!= HIDP_STATUS_SUCCESS
)
718 /* failed to get capabilities */
719 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status
);
720 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
724 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities
.Usage
, Capabilities
.UsagePage
, Capabilities
.InputReportByteLength
);
726 /* init input report */
727 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
728 ASSERT(DeviceExtension
->ReportLength
);
729 DeviceExtension
->Report
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExtension
->ReportLength
, KBDHID_TAG
);
730 ASSERT(DeviceExtension
->Report
);
731 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
734 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
,
735 DeviceExtension
->ReportLength
,
739 ASSERT(DeviceExtension
->ReportMDL
);
742 MmBuildMdlForNonPagedPool(DeviceExtension
->ReportMDL
);
744 /* get max number of buttons */
745 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_KEYBOARD
, PreparsedData
);
746 DPRINT("[KBDHID] Buttons %lu\n", Buttons
);
749 /* now allocate an array for those buttons */
750 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
, KBDHID_TAG
);
754 ExFreePoolWithTag(PreparsedData
, KBDHID_TAG
);
755 return STATUS_INSUFFICIENT_RESOURCES
;
757 DeviceExtension
->UsageListBuffer
= Buffer
;
759 /* init usage lists */
760 RtlZeroMemory(Buffer
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
761 DeviceExtension
->CurrentUsageList
= Buffer
;
763 DeviceExtension
->PreviousUsageList
= Buffer
;
765 DeviceExtension
->MakeUsageList
= Buffer
;
767 DeviceExtension
->BreakUsageList
= Buffer
;
770 // FIMXE: implement device hacks
773 // KeyboardTypeOverride
774 // KeyboardSubTypeOverride
775 // KeyboardNumberTotalKeysOverride
776 // KeyboardNumberFunctionKeysOverride
777 // KeyboardNumberIndicatorsOverride
779 /* store number of buttons */
780 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
782 /* store preparsed data */
783 DeviceExtension
->PreparsedData
= PreparsedData
;
785 /* completed successfully */
786 return STATUS_SUCCESS
;
791 KbdHid_StartDeviceCompletion(
792 IN PDEVICE_OBJECT DeviceObject
,
796 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
797 return STATUS_MORE_PROCESSING_REQUIRED
;
802 KbdHid_FreeResources(
803 IN PDEVICE_OBJECT DeviceObject
)
805 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
807 /* get device extension */
808 DeviceExtension
= DeviceObject
->DeviceExtension
;
811 if (DeviceExtension
->PreparsedData
)
813 ExFreePoolWithTag(DeviceExtension
->PreparsedData
, KBDHID_TAG
);
814 DeviceExtension
->PreparsedData
= NULL
;
817 if (DeviceExtension
->UsageListBuffer
)
819 ExFreePoolWithTag(DeviceExtension
->UsageListBuffer
, KBDHID_TAG
);
820 DeviceExtension
->UsageListBuffer
= NULL
;
821 DeviceExtension
->CurrentUsageList
= NULL
;
822 DeviceExtension
->PreviousUsageList
= NULL
;
823 DeviceExtension
->MakeUsageList
= NULL
;
824 DeviceExtension
->BreakUsageList
= NULL
;
827 if (DeviceExtension
->ReportMDL
)
829 IoFreeMdl(DeviceExtension
->ReportMDL
);
830 DeviceExtension
->ReportMDL
= NULL
;
833 if (DeviceExtension
->Report
)
835 ExFreePoolWithTag(DeviceExtension
->Report
, KBDHID_TAG
);
836 DeviceExtension
->Report
= NULL
;
839 return STATUS_SUCCESS
;
845 IN PDEVICE_OBJECT DeviceObject
,
848 PIO_STACK_LOCATION IoStack
;
849 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
851 /* get device extension */
852 DeviceExtension
= DeviceObject
->DeviceExtension
;
854 /* skip current stack location */
855 IoSkipCurrentIrpStackLocation(Irp
);
857 /* get next stack location */
858 IoStack
= IoGetNextIrpStackLocation(Irp
);
860 /* change request to hid flush queue request */
861 IoStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
862 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_HID_FLUSH_QUEUE
;
865 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
871 IN PDEVICE_OBJECT DeviceObject
,
874 PIO_STACK_LOCATION IoStack
;
877 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
879 /* get device extension */
880 DeviceExtension
= DeviceObject
->DeviceExtension
;
882 /* get current irp stack */
883 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
884 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack
->MinorFunction
);
886 switch (IoStack
->MinorFunction
)
888 case IRP_MN_STOP_DEVICE
:
889 case IRP_MN_SURPRISE_REMOVAL
:
891 KbdHid_FreeResources(DeviceObject
);
893 case IRP_MN_CANCEL_REMOVE_DEVICE
:
894 case IRP_MN_QUERY_STOP_DEVICE
:
895 case IRP_MN_CANCEL_STOP_DEVICE
:
896 case IRP_MN_QUERY_REMOVE_DEVICE
:
897 /* indicate success */
898 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
900 /* skip irp stack location */
901 IoSkipCurrentIrpStackLocation(Irp
);
903 /* dispatch to lower device */
904 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
906 case IRP_MN_REMOVE_DEVICE
:
907 /* FIXME synchronization */
910 IoCancelIrp(DeviceExtension
->Irp
);
913 KbdHid_FreeResources(DeviceObject
);
915 /* indicate success */
916 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
918 /* skip irp stack location */
919 IoSkipCurrentIrpStackLocation(Irp
);
921 /* dispatch to lower device */
922 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
924 IoFreeIrp(DeviceExtension
->Irp
);
925 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
926 IoDeleteDevice(DeviceObject
);
929 case IRP_MN_START_DEVICE
:
931 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
933 /* copy stack location */
934 IoCopyCurrentIrpStackLocationToNext (Irp
);
936 /* set completion routine */
937 IoSetCompletionRoutine(Irp
, KbdHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
938 Irp
->IoStatus
.Status
= 0;
941 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
942 if (Status
== STATUS_PENDING
)
944 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
945 Status
= Irp
->IoStatus
.Status
;
948 if (!NT_SUCCESS(Status
))
951 Irp
->IoStatus
.Status
= Status
;
952 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
956 /* lets start the device */
957 Status
= KbdHid_StartDevice(DeviceObject
);
958 DPRINT("KbdHid_StartDevice %x\n", Status
);
960 /* complete request */
961 Irp
->IoStatus
.Status
= Status
;
962 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
968 /* skip irp stack location */
969 IoSkipCurrentIrpStackLocation(Irp
);
971 /* dispatch to lower device */
972 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
979 IN PDRIVER_OBJECT DriverObject
,
980 IN PDEVICE_OBJECT PhysicalDeviceObject
)
983 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
984 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
987 /* create device object */
988 Status
= IoCreateDevice(DriverObject
,
989 sizeof(KBDHID_DEVICE_EXTENSION
),
991 FILE_DEVICE_KEYBOARD
,
995 if (!NT_SUCCESS(Status
))
997 /* failed to create device object */
1002 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
1003 if (!NextDeviceObject
)
1005 /* failed to attach */
1006 IoDeleteDevice(DeviceObject
);
1007 return STATUS_DEVICE_NOT_CONNECTED
;
1010 /* get device extension */
1011 DeviceExtension
= DeviceObject
->DeviceExtension
;
1013 /* zero extension */
1014 RtlZeroMemory(DeviceExtension
, sizeof(KBDHID_DEVICE_EXTENSION
));
1016 /* init device extension */
1017 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
1018 KeInitializeEvent(&DeviceExtension
->ReadCompletionEvent
, NotificationEvent
, FALSE
);
1020 /* init keyboard attributes */
1021 DeviceExtension
->Attributes
.KeyboardIdentifier
.Type
= KEYBOARD_TYPE_UNKNOWN
;
1022 DeviceExtension
->Attributes
.KeyboardIdentifier
.Subtype
= MICROSOFT_KBD_101_TYPE
;
1023 DeviceExtension
->Attributes
.NumberOfFunctionKeys
= MICROSOFT_KBD_FUNC
;
1024 DeviceExtension
->Attributes
.NumberOfIndicators
= 3; // caps, num lock, scroll lock
1025 DeviceExtension
->Attributes
.NumberOfKeysTotal
= 101;
1026 DeviceExtension
->Attributes
.InputDataQueueLength
= 1;
1027 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Rate
= KEYBOARD_TYPEMATIC_RATE_MINIMUM
;
1028 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MINIMUM
;
1029 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Rate
= KEYBOARD_TYPEMATIC_RATE_DEFAULT
;
1030 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MAXIMUM
;
1033 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
1035 /* FIXME handle allocation error */
1036 ASSERT(DeviceExtension
->Irp
);
1038 /* set power state to D0 */
1039 State
.DeviceState
= PowerDeviceD0
;
1040 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
1042 /* init device object */
1043 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
1044 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1046 /* completed successfully */
1047 return STATUS_SUCCESS
;
1053 IN PDRIVER_OBJECT DriverObject
)
1062 IN PDRIVER_OBJECT DriverObject
,
1063 IN PUNICODE_STRING RegPath
)
1065 /* initialize driver object */
1066 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdHid_Create
;
1067 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdHid_Close
;
1068 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = KbdHid_Flush
;
1069 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdHid_DeviceControl
;
1070 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = KbdHid_InternalDeviceControl
;
1071 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KbdHid_Power
;
1072 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KbdHid_Pnp
;
1073 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KbdHid_SystemControl
;
1074 DriverObject
->DriverUnload
= KbdHid_Unload
;
1075 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
1078 return STATUS_SUCCESS
;