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
= (PKBDHID_DEVICE_EXTENSION
)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((PKBDHID_DEVICE_EXTENSION
)Context
, &InputData
);
97 KbdHid_ReadCompletion(
98 IN PDEVICE_OBJECT DeviceObject
,
102 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
106 /* get device extension */
107 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)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
, HIDP_LINK_COLLECTION_UNSPECIFIED
, DeviceExtension
->CurrentUsageList
, &ButtonLength
, DeviceExtension
->PreparsedData
, DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
140 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
142 /* FIXME check if needs mapping */
144 /* get usage difference */
145 Status
= HidP_UsageAndPageListDifference(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, DeviceExtension
->BreakUsageList
, DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
);
146 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
148 /* replace previous usage list with current list */
149 RtlMoveMemory(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, sizeof(USAGE_AND_PAGE
) * DeviceExtension
->UsageListLength
);
151 /* translate break usage list */
152 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->BreakUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Break
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
153 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
155 /* translate new usage list */
156 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Make
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
157 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
160 KbdHid_InitiateRead(DeviceExtension
);
162 /* stop completion */
163 return STATUS_MORE_PROCESSING_REQUIRED
;
168 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
)
170 PIO_STACK_LOCATION IoStack
;
174 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
177 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
179 /* get next stack location */
180 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
182 /* init stack location */
183 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
184 IoStack
->Parameters
.Read
.Key
= 0;
185 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
186 IoStack
->MajorFunction
= IRP_MJ_READ
;
187 IoStack
->FileObject
= DeviceExtension
->FileObject
;
189 /* set completion routine */
190 IoSetCompletionRoutine(DeviceExtension
->Irp
, KbdHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
193 DeviceExtension
->ReadReportActive
= TRUE
;
196 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
204 KbdHid_CreateCompletion(
205 IN PDEVICE_OBJECT DeviceObject
,
209 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
210 return STATUS_MORE_PROCESSING_REQUIRED
;
217 IN PDEVICE_OBJECT DeviceObject
,
220 PIO_STACK_LOCATION IoStack
;
223 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
225 DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
227 /* get device extension */
228 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
230 /* get stack location */
231 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
233 /* copy stack location to next */
234 IoCopyCurrentIrpStackLocationToNext(Irp
);
237 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
240 IoSetCompletionRoutine(Irp
, KbdHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
242 /* call lower driver */
243 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
244 if (Status
== STATUS_PENDING
)
246 /* request pending */
247 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
250 /* check for success */
251 if (!NT_SUCCESS(Status
))
254 Irp
->IoStatus
.Status
= Status
;
255 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
259 /* is the driver already in use */
260 if (DeviceExtension
->FileObject
== NULL
)
262 /* did the caller specify correct attributes */
263 ASSERT(IoStack
->Parameters
.Create
.SecurityContext
);
264 if (IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
)
266 /* store file object */
267 DeviceExtension
->FileObject
= IoStack
->FileObject
;
270 KeResetEvent(&DeviceExtension
->ReadCompletionEvent
);
272 /* initiating read */
273 Status
= KbdHid_InitiateRead(DeviceExtension
);
274 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status
);
275 if (Status
== STATUS_PENDING
)
277 /* report irp is pending */
278 Status
= STATUS_SUCCESS
;
283 /* complete request */
284 Irp
->IoStatus
.Status
= Status
;
285 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
293 IN PDEVICE_OBJECT DeviceObject
,
296 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
298 /* get device extension */
299 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
301 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
303 if (DeviceExtension
->ReadReportActive
)
305 /* request stopping of the report cycle */
306 DeviceExtension
->StopReadReport
= TRUE
;
308 /* wait until the reports have been read */
309 KeWaitForSingleObject(&DeviceExtension
->ReadCompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
312 IoCancelIrp(DeviceExtension
->Irp
);
315 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
317 /* remove file object */
318 DeviceExtension
->FileObject
= NULL
;
321 IoSkipCurrentIrpStackLocation(Irp
);
323 /* pass irp to down the stack */
324 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
329 KbdHid_InternalDeviceControl(
330 IN PDEVICE_OBJECT DeviceObject
,
333 PIO_STACK_LOCATION IoStack
;
334 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
336 PKEYBOARD_ATTRIBUTES Attributes
;
338 /* get current stack location */
339 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
341 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
343 /* get device extension */
344 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
346 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_ATTRIBUTES
)
348 /* verify output buffer length */
349 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUSE_ATTRIBUTES
))
351 /* invalid request */
352 DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
353 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
354 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
355 return STATUS_BUFFER_TOO_SMALL
;
358 /* get output buffer */
359 Attributes
= (PKEYBOARD_ATTRIBUTES
)Irp
->AssociatedIrp
.SystemBuffer
;
361 /* copy attributes */
362 RtlCopyMemory(Attributes
, &DeviceExtension
->Attributes
, sizeof(KEYBOARD_ATTRIBUTES
));
364 /* complete request */
365 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
366 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
367 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
368 return STATUS_SUCCESS
;
370 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_CONNECT
)
372 /* verify input buffer length */
373 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
375 /* invalid request */
376 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
377 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
378 return STATUS_INVALID_PARAMETER
;
381 /* is it already connected */
382 if (DeviceExtension
->ClassService
)
384 /* already connected */
385 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
386 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
387 return STATUS_SHARING_VIOLATION
;
390 /* get connect data */
391 Data
= (PCONNECT_DATA
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
393 /* store connect details */
394 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
395 DeviceExtension
->ClassService
= Data
->ClassService
;
397 /* completed successfully */
398 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
399 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
400 return STATUS_SUCCESS
;
402 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISCONNECT
)
404 /* not implemented */
405 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
406 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
407 return STATUS_NOT_IMPLEMENTED
;
409 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_ENABLE
)
412 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
413 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
414 return STATUS_NOT_SUPPORTED
;
416 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISABLE
)
419 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
420 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
421 return STATUS_NOT_SUPPORTED
;
423 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATORS
)
425 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
427 /* invalid parameter */
428 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
429 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
430 return STATUS_INVALID_PARAMETER
;
433 /* copy indicators */
434 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &DeviceExtension
->KeyboardIndicator
, sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
436 /* complete request */
437 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
438 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INDICATOR_PARAMETERS
);
439 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
440 return STATUS_NOT_IMPLEMENTED
;
442 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_TYPEMATIC
)
444 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
446 /* invalid parameter */
447 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
448 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
449 return STATUS_INVALID_PARAMETER
;
452 /* copy indicators */
453 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &DeviceExtension
->KeyboardTypematic
, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
456 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
457 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
);
458 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
459 return STATUS_SUCCESS
;
461 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_INDICATORS
)
463 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
465 /* invalid parameter */
466 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
467 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
468 return STATUS_INVALID_PARAMETER
;
471 /* copy indicators */
472 RtlCopyMemory(&DeviceExtension
->KeyboardIndicator
, Irp
->AssociatedIrp
.SystemBuffer
, sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
475 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
476 Irp
->IoStatus
.Information
= 0;
477 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
478 return STATUS_SUCCESS
;
480 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_TYPEMATIC
)
482 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
484 /* invalid parameter */
485 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
486 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
487 return STATUS_INVALID_PARAMETER
;
490 /* copy indicators */
491 RtlCopyMemory(&DeviceExtension
->KeyboardTypematic
, Irp
->AssociatedIrp
.SystemBuffer
, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
494 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
495 Irp
->IoStatus
.Information
= 0;
496 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
497 return STATUS_SUCCESS
;
499 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
)
501 /* not implemented */
502 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
503 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
504 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
505 return STATUS_NOT_IMPLEMENTED
;
508 /* unknown control code */
509 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
510 /* unknown request not supported */
511 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
512 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
513 return STATUS_NOT_SUPPORTED
;
518 KbdHid_DeviceControl(
519 IN PDEVICE_OBJECT DeviceObject
,
522 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
524 /* get device extension */
525 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
527 /* skip stack location */
528 IoSkipCurrentIrpStackLocation(Irp
);
530 /* pass and forget */
531 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
537 IN PDEVICE_OBJECT DeviceObject
,
541 return STATUS_NOT_IMPLEMENTED
;
545 KbdHid_SubmitRequest(
546 PDEVICE_OBJECT DeviceObject
,
548 ULONG InputBufferSize
,
550 ULONG OutputBufferSize
,
554 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
557 IO_STATUS_BLOCK IoStatus
;
559 /* get device extension */
560 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
563 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
566 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceExtension
->NextDeviceObject
, InputBuffer
, InputBufferSize
, OutputBuffer
, OutputBufferSize
, FALSE
, &Event
, &IoStatus
);
570 return STATUS_INSUFFICIENT_RESOURCES
;
574 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
575 if (Status
== STATUS_PENDING
)
577 /* wait for request to complete */
578 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
579 Status
= IoStatus
.Status
;
589 IN PDEVICE_OBJECT DeviceObject
)
593 HID_COLLECTION_INFORMATION Information
;
594 PHIDP_PREPARSED_DATA PreparsedData
;
595 HIDP_CAPS Capabilities
;
596 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
597 PUSAGE_AND_PAGE Buffer
;
599 /* get device extension */
600 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
602 /* query collection information */
603 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_INFORMATION
, 0, NULL
, sizeof(HID_COLLECTION_INFORMATION
), &Information
);
604 if (!NT_SUCCESS(Status
))
606 /* failed to query collection information */
607 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
611 /* lets allocate space for preparsed data */
612 PreparsedData
= (PHIDP_PREPARSED_DATA
)ExAllocatePool(NonPagedPool
, Information
.DescriptorSize
);
616 DPRINT1("[KBDHID] no memory size %u\n", Information
.DescriptorSize
);
617 return STATUS_INSUFFICIENT_RESOURCES
;
620 /* now obtain the preparsed data */
621 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_DESCRIPTOR
, 0, NULL
, Information
.DescriptorSize
, PreparsedData
);
622 if (!NT_SUCCESS(Status
))
624 /* failed to get preparsed data */
625 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
626 ExFreePool(PreparsedData
);
630 /* lets get the caps */
631 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
632 if (Status
!= HIDP_STATUS_SUCCESS
)
634 /* failed to get capabilities */
635 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status
);
636 ExFreePool(PreparsedData
);
640 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities
.Usage
, Capabilities
.UsagePage
, Capabilities
.InputReportByteLength
);
642 /* init input report*/
643 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
644 ASSERT(DeviceExtension
->ReportLength
);
645 DeviceExtension
->Report
= (PCHAR
)ExAllocatePool(NonPagedPool
, DeviceExtension
->ReportLength
);
646 ASSERT(DeviceExtension
->Report
);
647 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
650 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
, DeviceExtension
->ReportLength
, FALSE
, FALSE
, NULL
);
651 ASSERT(DeviceExtension
->ReportMDL
);
654 MmBuildMdlForNonPagedPool(DeviceExtension
->ReportMDL
);
656 /* get max number of buttons */
657 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_KEYBOARD
, PreparsedData
);
658 DPRINT("[KBDHID] Buttons %lu\n", Buttons
);
661 /* now allocate an array for those buttons */
662 Buffer
= (PUSAGE_AND_PAGE
)ExAllocatePool(NonPagedPool
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
666 ExFreePool(PreparsedData
);
667 return STATUS_INSUFFICIENT_RESOURCES
;
670 /* init usage lists */
671 RtlZeroMemory(Buffer
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
672 DeviceExtension
->CurrentUsageList
= Buffer
;
674 DeviceExtension
->PreviousUsageList
= Buffer
;
676 DeviceExtension
->MakeUsageList
= Buffer
;
678 DeviceExtension
->BreakUsageList
= Buffer
;
681 // FIMXE: implement device hacks
684 // KeyboardTypeOverride
685 // KeyboardSubTypeOverride
686 // KeyboardNumberTotalKeysOverride
687 // KeyboardNumberFunctionKeysOverride
688 // KeyboardNumberIndicatorsOverride
690 /* store number of buttons */
691 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
693 /* store preparsed data */
694 DeviceExtension
->PreparsedData
= PreparsedData
;
696 /* completed successfully */
697 return STATUS_SUCCESS
;
702 KbdHid_StartDeviceCompletion(
703 IN PDEVICE_OBJECT DeviceObject
,
707 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
708 return STATUS_MORE_PROCESSING_REQUIRED
;
714 IN PDEVICE_OBJECT DeviceObject
,
717 PIO_STACK_LOCATION IoStack
;
718 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
720 /* get device extension */
721 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
723 /* skip current stack location */
724 IoSkipCurrentIrpStackLocation(Irp
);
726 /* get next stack location */
727 IoStack
= IoGetNextIrpStackLocation(Irp
);
729 /* change request to hid flush queue request */
730 IoStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
731 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_HID_FLUSH_QUEUE
;
734 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
740 IN PDEVICE_OBJECT DeviceObject
,
743 PIO_STACK_LOCATION IoStack
;
746 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
748 /* get device extension */
749 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
751 /* get current irp stack */
752 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
753 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack
->MinorFunction
);
755 if (IoStack
->MinorFunction
== IRP_MN_STOP_DEVICE
||
756 IoStack
->MinorFunction
== IRP_MN_CANCEL_REMOVE_DEVICE
||
757 IoStack
->MinorFunction
== IRP_MN_QUERY_STOP_DEVICE
||
758 IoStack
->MinorFunction
== IRP_MN_CANCEL_STOP_DEVICE
||
759 IoStack
->MinorFunction
== IRP_MN_QUERY_REMOVE_DEVICE
)
761 /* indicate success */
762 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
764 /* skip irp stack location */
765 IoSkipCurrentIrpStackLocation(Irp
);
767 /* dispatch to lower device */
768 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
770 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
772 /* FIXME synchronization */
775 IoCancelIrp(DeviceExtension
->Irp
);
777 /* indicate success */
778 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
780 /* skip irp stack location */
781 IoSkipCurrentIrpStackLocation(Irp
);
783 /* dispatch to lower device */
784 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
786 IoFreeIrp(DeviceExtension
->Irp
);
787 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
788 IoDeleteDevice(DeviceObject
);
791 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
794 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
796 /* copy stack location */
797 IoCopyCurrentIrpStackLocationToNext (Irp
);
799 /* set completion routine */
800 IoSetCompletionRoutine(Irp
, KbdHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
801 Irp
->IoStatus
.Status
= 0;
804 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
805 if (Status
== STATUS_PENDING
)
807 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
808 Status
= Irp
->IoStatus
.Status
;
811 if (!NT_SUCCESS(Status
))
814 Irp
->IoStatus
.Status
= Status
;
815 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
819 /* lets start the device */
820 Status
= KbdHid_StartDevice(DeviceObject
);
821 DPRINT("KbdHid_StartDevice %x\n", Status
);
823 /* complete request */
824 Irp
->IoStatus
.Status
= Status
;
825 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
832 /* skip irp stack location */
833 IoSkipCurrentIrpStackLocation(Irp
);
835 /* dispatch to lower device */
836 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
843 IN PDRIVER_OBJECT DriverObject
,
844 IN PDEVICE_OBJECT PhysicalDeviceObject
)
847 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
848 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
851 /* create device object */
852 Status
= IoCreateDevice(DriverObject
, sizeof(KBDHID_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KEYBOARD
, 0, FALSE
, &DeviceObject
);
853 if (!NT_SUCCESS(Status
))
855 /* failed to create device object */
860 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
861 if (!NextDeviceObject
)
863 /* failed to attach */
864 IoDeleteDevice(DeviceObject
);
865 return STATUS_DEVICE_NOT_CONNECTED
;
868 /* get device extension */
869 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
872 RtlZeroMemory(DeviceExtension
, sizeof(KBDHID_DEVICE_EXTENSION
));
874 /* init device extension */
875 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
876 KeInitializeEvent(&DeviceExtension
->ReadCompletionEvent
, NotificationEvent
, FALSE
);
878 /* init keyboard attributes */
879 DeviceExtension
->Attributes
.KeyboardIdentifier
.Type
= KEYBOARD_TYPE_UNKNOWN
;
880 DeviceExtension
->Attributes
.KeyboardIdentifier
.Subtype
= MICROSOFT_KBD_101_TYPE
;
881 DeviceExtension
->Attributes
.NumberOfFunctionKeys
= MICROSOFT_KBD_FUNC
;
882 DeviceExtension
->Attributes
.NumberOfIndicators
= 3; // caps, num lock, scroll lock
883 DeviceExtension
->Attributes
.NumberOfKeysTotal
= 101;
884 DeviceExtension
->Attributes
.InputDataQueueLength
= 1;
885 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Rate
= KEYBOARD_TYPEMATIC_RATE_MINIMUM
;
886 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MINIMUM
;
887 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Rate
= KEYBOARD_TYPEMATIC_RATE_DEFAULT
;
888 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MAXIMUM
;
891 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
893 /* FIXME handle allocation error */
894 ASSERT(DeviceExtension
->Irp
);
896 /* set power state to D0 */
897 State
.DeviceState
= PowerDeviceD0
;
898 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
900 /* init device object */
901 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
902 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
904 /* completed successfully */
905 return STATUS_SUCCESS
;
911 IN PDRIVER_OBJECT DriverObject
)
920 IN PDRIVER_OBJECT DriverObject
,
921 IN PUNICODE_STRING RegPath
)
923 /* initialize driver object */
924 DriverObject
->DriverUnload
= KbdHid_Unload
;
925 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
926 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdHid_Create
;
927 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdHid_Close
;
928 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = KbdHid_Flush
;
929 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdHid_DeviceControl
;
930 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = KbdHid_InternalDeviceControl
;
931 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KbdHid_Power
;
932 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KbdHid_Pnp
;
933 DriverObject
->DriverUnload
= KbdHid_Unload
;
934 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
937 return STATUS_SUCCESS
;