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
;
49 /* get device extension */
50 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)Context
;
52 for(Index
= 0; Index
< Length
; Index
++)
54 DPRINT("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index
, NewScanCodes
[Index
] & 0xFF);
57 RtlZeroMemory(&InputData
, sizeof(KEYBOARD_INPUT_DATA
));
59 /* use keyboard unit id */
60 InputData
.UnitId
= DeviceExtension
->KeyboardTypematic
.UnitId
;
62 if (((UCHAR
)(NewScanCodes
[Index
] & 0xFF))> 0x7F)
64 /* scan codes greater than 0x7F are a key break */
65 InputData
.Flags
|= KEY_BREAK
;
69 InputData
.MakeCode
= NewScanCodes
[Index
];
71 /* dispatch scan codes */
72 KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION
)Context
, &InputData
);
82 KbdHid_ReadCompletion(
83 IN PDEVICE_OBJECT DeviceObject
,
87 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
91 /* get device extension */
92 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)Context
;
94 if (Irp
->IoStatus
.Status
== STATUS_PRIVILEGE_NOT_HELD
||
95 Irp
->IoStatus
.Status
== STATUS_DEVICE_NOT_CONNECTED
||
96 Irp
->IoStatus
.Status
== STATUS_CANCELLED
||
97 DeviceExtension
->StopReadReport
)
99 /* failed to read or should be stopped*/
100 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp
->IoStatus
.Status
);
102 /* report no longer active */
103 DeviceExtension
->ReadReportActive
= FALSE
;
105 /* request stopping of the report cycle */
106 DeviceExtension
->StopReadReport
= FALSE
;
108 /* signal completion event */
109 KeSetEvent(&DeviceExtension
->ReadCompletionEvent
, 0, 0);
110 return STATUS_MORE_PROCESSING_REQUIRED
;
114 // print out raw report
116 ASSERT(DeviceExtension
->ReportLength
>= 9);
117 DPRINT("[KBDHID] ReadCompletion %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DeviceExtension
->Report
[0], DeviceExtension
->Report
[1], DeviceExtension
->Report
[2],
118 DeviceExtension
->Report
[3], DeviceExtension
->Report
[4], DeviceExtension
->Report
[5],
119 DeviceExtension
->Report
[6], DeviceExtension
->Report
[7], DeviceExtension
->Report
[8]);
122 /* get current usages */
123 ButtonLength
= DeviceExtension
->UsageListLength
;
124 Status
= HidP_GetUsagesEx(HidP_Input
, HIDP_LINK_COLLECTION_UNSPECIFIED
, DeviceExtension
->CurrentUsageList
, &ButtonLength
, DeviceExtension
->PreparsedData
, DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
125 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
127 /* FIXME check if needs mapping */
129 /* get usage difference */
130 Status
= HidP_UsageAndPageListDifference(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, DeviceExtension
->BreakUsageList
, DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
);
131 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
133 /* replace previous usage list with current list */
134 RtlMoveMemory(DeviceExtension
->PreviousUsageList
, DeviceExtension
->CurrentUsageList
, sizeof(USAGE_AND_PAGE
) * DeviceExtension
->UsageListLength
);
136 /* translate break usage list */
137 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->BreakUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Break
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
138 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
140 /* translate new usage list */
141 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension
->MakeUsageList
, DeviceExtension
->UsageListLength
, HidP_Keyboard_Make
, &DeviceExtension
->ModifierState
, KbdHid_InsertScanCodes
, DeviceExtension
);
142 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
145 KbdHid_InitiateRead(DeviceExtension
);
147 /* stop completion */
148 return STATUS_MORE_PROCESSING_REQUIRED
;
153 IN PKBDHID_DEVICE_EXTENSION DeviceExtension
)
155 PIO_STACK_LOCATION IoStack
;
159 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
162 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
164 /* get next stack location */
165 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
167 /* init stack location */
168 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
169 IoStack
->Parameters
.Read
.Key
= 0;
170 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
171 IoStack
->MajorFunction
= IRP_MJ_READ
;
172 IoStack
->FileObject
= DeviceExtension
->FileObject
;
174 /* set completion routine */
175 IoSetCompletionRoutine(DeviceExtension
->Irp
, KbdHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
178 DeviceExtension
->ReadReportActive
= TRUE
;
181 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
189 KbdHid_CreateCompletion(
190 IN PDEVICE_OBJECT DeviceObject
,
194 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
195 return STATUS_MORE_PROCESSING_REQUIRED
;
202 IN PDEVICE_OBJECT DeviceObject
,
205 PIO_STACK_LOCATION IoStack
;
208 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
210 DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
212 /* get device extension */
213 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
215 /* get stack location */
216 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
218 /* copy stack location to next */
219 IoCopyCurrentIrpStackLocationToNext(Irp
);
222 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
225 IoSetCompletionRoutine(Irp
, KbdHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
227 /* call lower driver */
228 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
229 if (Status
== STATUS_PENDING
)
231 /* request pending */
232 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
235 /* check for success */
236 if (!NT_SUCCESS(Status
))
239 Irp
->IoStatus
.Status
= Status
;
240 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
244 /* is the driver already in use */
245 if (DeviceExtension
->FileObject
== NULL
)
247 /* did the caller specify correct attributes */
248 ASSERT(IoStack
->Parameters
.Create
.SecurityContext
);
249 if (IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
)
251 /* store file object */
252 DeviceExtension
->FileObject
= IoStack
->FileObject
;
255 KeResetEvent(&DeviceExtension
->ReadCompletionEvent
);
257 /* initiating read */
258 Status
= KbdHid_InitiateRead(DeviceExtension
);
259 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status
);
260 if (Status
== STATUS_PENDING
)
262 /* report irp is pending */
263 Status
= STATUS_SUCCESS
;
268 /* complete request */
269 Irp
->IoStatus
.Status
= Status
;
270 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
278 IN PDEVICE_OBJECT DeviceObject
,
281 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
283 /* get device extension */
284 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
286 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
288 if (DeviceExtension
->ReadReportActive
)
290 /* request stopping of the report cycle */
291 DeviceExtension
->StopReadReport
= TRUE
;
293 /* wait until the reports have been read */
294 KeWaitForSingleObject(&DeviceExtension
->ReadCompletionEvent
, Executive
, KernelMode
, FALSE
, NULL
);
297 IoCancelIrp(DeviceExtension
->Irp
);
300 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension
->ReadReportActive
);
302 /* remove file object */
303 DeviceExtension
->FileObject
= NULL
;
306 IoSkipCurrentIrpStackLocation(Irp
);
308 /* pass irp to down the stack */
309 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
314 KbdHid_InternalDeviceControl(
315 IN PDEVICE_OBJECT DeviceObject
,
318 PIO_STACK_LOCATION IoStack
;
319 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
321 PKEYBOARD_ATTRIBUTES Attributes
;
323 /* get current stack location */
324 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
326 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
328 /* get device extension */
329 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
331 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_ATTRIBUTES
)
333 /* verify output buffer length */
334 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUSE_ATTRIBUTES
))
336 /* invalid request */
337 DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
338 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
339 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
340 return STATUS_BUFFER_TOO_SMALL
;
343 /* get output buffer */
344 Attributes
= (PKEYBOARD_ATTRIBUTES
)Irp
->AssociatedIrp
.SystemBuffer
;
346 /* copy attributes */
347 RtlCopyMemory(Attributes
, &DeviceExtension
->Attributes
, sizeof(KEYBOARD_ATTRIBUTES
));
349 /* complete request */
350 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
351 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
352 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
353 return STATUS_SUCCESS
;
355 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_CONNECT
)
357 /* verify input buffer length */
358 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
360 /* invalid request */
361 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
362 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
363 return STATUS_INVALID_PARAMETER
;
366 /* is it already connected */
367 if (DeviceExtension
->ClassService
)
369 /* already connected */
370 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
371 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
372 return STATUS_SHARING_VIOLATION
;
375 /* get connect data */
376 Data
= (PCONNECT_DATA
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
378 /* store connect details */
379 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
380 DeviceExtension
->ClassService
= Data
->ClassService
;
382 /* completed successfully */
383 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
384 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
385 return STATUS_SUCCESS
;
387 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISCONNECT
)
389 /* not implemented */
390 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
391 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
392 return STATUS_NOT_IMPLEMENTED
;
394 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_ENABLE
)
397 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
398 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
399 return STATUS_NOT_SUPPORTED
;
401 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_KEYBOARD_DISABLE
)
404 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
405 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
406 return STATUS_NOT_SUPPORTED
;
408 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATORS
)
410 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
412 /* invalid parameter */
413 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
414 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
415 return STATUS_INVALID_PARAMETER
;
418 /* copy indicators */
419 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &DeviceExtension
->KeyboardIndicator
, sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
421 /* complete request */
422 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
423 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_INDICATOR_PARAMETERS
);
424 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
425 return STATUS_NOT_IMPLEMENTED
;
427 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_TYPEMATIC
)
429 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
431 /* invalid parameter */
432 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
433 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
434 return STATUS_INVALID_PARAMETER
;
437 /* copy indicators */
438 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &DeviceExtension
->KeyboardTypematic
, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
441 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
442 Irp
->IoStatus
.Information
= sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
);
443 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
444 return STATUS_SUCCESS
;
446 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_INDICATORS
)
448 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_INDICATOR_PARAMETERS
))
450 /* invalid parameter */
451 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
452 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
453 return STATUS_INVALID_PARAMETER
;
456 /* copy indicators */
457 RtlCopyMemory(&DeviceExtension
->KeyboardIndicator
, Irp
->AssociatedIrp
.SystemBuffer
, sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
460 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
461 Irp
->IoStatus
.Information
= 0;
462 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
463 return STATUS_SUCCESS
;
465 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_SET_TYPEMATIC
)
467 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
))
469 /* invalid parameter */
470 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
471 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
472 return STATUS_INVALID_PARAMETER
;
475 /* copy indicators */
476 RtlCopyMemory(&DeviceExtension
->KeyboardTypematic
, Irp
->AssociatedIrp
.SystemBuffer
, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
479 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
480 Irp
->IoStatus
.Information
= 0;
481 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
482 return STATUS_SUCCESS
;
484 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
)
486 /* not implemented */
487 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
488 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
489 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
490 return STATUS_NOT_IMPLEMENTED
;
493 /* unknown control code */
494 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
495 /* unknown request not supported */
496 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
497 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
498 return STATUS_NOT_SUPPORTED
;
503 KbdHid_DeviceControl(
504 IN PDEVICE_OBJECT DeviceObject
,
507 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
509 /* get device extension */
510 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
512 /* skip stack location */
513 IoSkipCurrentIrpStackLocation(Irp
);
515 /* pass and forget */
516 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
522 IN PDEVICE_OBJECT DeviceObject
,
526 return STATUS_NOT_IMPLEMENTED
;
530 KbdHid_SubmitRequest(
531 PDEVICE_OBJECT DeviceObject
,
533 ULONG InputBufferSize
,
535 ULONG OutputBufferSize
,
539 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
542 IO_STATUS_BLOCK IoStatus
;
544 /* get device extension */
545 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
548 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
551 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceExtension
->NextDeviceObject
, InputBuffer
, InputBufferSize
, OutputBuffer
, OutputBufferSize
, FALSE
, &Event
, &IoStatus
);
555 return STATUS_INSUFFICIENT_RESOURCES
;
559 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
560 if (Status
== STATUS_PENDING
)
562 /* wait for request to complete */
563 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
564 Status
= IoStatus
.Status
;
574 IN PDEVICE_OBJECT DeviceObject
)
578 HID_COLLECTION_INFORMATION Information
;
579 PHIDP_PREPARSED_DATA PreparsedData
;
580 HIDP_CAPS Capabilities
;
581 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
582 PUSAGE_AND_PAGE Buffer
;
584 /* get device extension */
585 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
587 /* query collection information */
588 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_INFORMATION
, 0, NULL
, sizeof(HID_COLLECTION_INFORMATION
), &Information
);
589 if (!NT_SUCCESS(Status
))
591 /* failed to query collection information */
592 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
596 /* lets allocate space for preparsed data */
597 PreparsedData
= (PHIDP_PREPARSED_DATA
)ExAllocatePool(NonPagedPool
, Information
.DescriptorSize
);
601 DPRINT1("[KBDHID] no memory size %u\n", Information
.DescriptorSize
);
602 return STATUS_INSUFFICIENT_RESOURCES
;
605 /* now obtain the preparsed data */
606 Status
= KbdHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_DESCRIPTOR
, 0, NULL
, Information
.DescriptorSize
, PreparsedData
);
607 if (!NT_SUCCESS(Status
))
609 /* failed to get preparsed data */
610 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status
);
611 ExFreePool(PreparsedData
);
615 /* lets get the caps */
616 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
617 if (Status
!= HIDP_STATUS_SUCCESS
)
619 /* failed to get capabilities */
620 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status
);
621 ExFreePool(PreparsedData
);
625 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities
.Usage
, Capabilities
.UsagePage
, Capabilities
.InputReportByteLength
);
627 /* init input report*/
628 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
629 ASSERT(DeviceExtension
->ReportLength
);
630 DeviceExtension
->Report
= (PCHAR
)ExAllocatePool(NonPagedPool
, DeviceExtension
->ReportLength
);
631 ASSERT(DeviceExtension
->Report
);
632 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
635 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
, DeviceExtension
->ReportLength
, FALSE
, FALSE
, NULL
);
636 ASSERT(DeviceExtension
->ReportMDL
);
639 MmBuildMdlForNonPagedPool(DeviceExtension
->ReportMDL
);
641 /* get max number of buttons */
642 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_KEYBOARD
, PreparsedData
);
643 DPRINT("[KBDHID] Buttons %lu\n", Buttons
);
646 /* now allocate an array for those buttons */
647 Buffer
= (PUSAGE_AND_PAGE
)ExAllocatePool(NonPagedPool
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
651 ExFreePool(PreparsedData
);
652 return STATUS_INSUFFICIENT_RESOURCES
;
655 /* init usage lists */
656 RtlZeroMemory(Buffer
, sizeof(USAGE_AND_PAGE
) * 4 * Buttons
);
657 DeviceExtension
->CurrentUsageList
= Buffer
;
659 DeviceExtension
->PreviousUsageList
= Buffer
;
661 DeviceExtension
->MakeUsageList
= Buffer
;
663 DeviceExtension
->BreakUsageList
= Buffer
;
666 // FIMXE: implement device hacks
669 // KeyboardTypeOverride
670 // KeyboardSubTypeOverride
671 // KeyboardNumberTotalKeysOverride
672 // KeyboardNumberFunctionKeysOverride
673 // KeyboardNumberIndicatorsOverride
675 /* store number of buttons */
676 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
678 /* store preparsed data */
679 DeviceExtension
->PreparsedData
= PreparsedData
;
681 /* completed successfully */
682 return STATUS_SUCCESS
;
687 KbdHid_StartDeviceCompletion(
688 IN PDEVICE_OBJECT DeviceObject
,
692 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
693 return STATUS_MORE_PROCESSING_REQUIRED
;
699 IN PDEVICE_OBJECT DeviceObject
,
702 PIO_STACK_LOCATION IoStack
;
703 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
705 /* get device extension */
706 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
708 /* skip current stack location */
709 IoSkipCurrentIrpStackLocation(Irp
);
711 /* get next stack location */
712 IoStack
= IoGetNextIrpStackLocation(Irp
);
714 /* change request to hid flush queue request */
715 IoStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
716 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_HID_FLUSH_QUEUE
;
719 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
725 IN PDEVICE_OBJECT DeviceObject
,
728 PIO_STACK_LOCATION IoStack
;
731 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
733 /* get device extension */
734 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
736 /* get current irp stack */
737 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
738 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack
->MinorFunction
);
740 if (IoStack
->MinorFunction
== IRP_MN_STOP_DEVICE
||
741 IoStack
->MinorFunction
== IRP_MN_CANCEL_REMOVE_DEVICE
||
742 IoStack
->MinorFunction
== IRP_MN_QUERY_STOP_DEVICE
||
743 IoStack
->MinorFunction
== IRP_MN_CANCEL_STOP_DEVICE
||
744 IoStack
->MinorFunction
== IRP_MN_QUERY_REMOVE_DEVICE
)
746 /* indicate success */
747 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
749 /* skip irp stack location */
750 IoSkipCurrentIrpStackLocation(Irp
);
752 /* dispatch to lower device */
753 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
755 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
757 /* FIXME synchronization */
760 IoCancelIrp(DeviceExtension
->Irp
);
762 /* indicate success */
763 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
765 /* skip irp stack location */
766 IoSkipCurrentIrpStackLocation(Irp
);
768 /* dispatch to lower device */
769 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
771 IoFreeIrp(DeviceExtension
->Irp
);
772 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
773 IoDeleteDevice(DeviceObject
);
776 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
779 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
781 /* copy stack location */
782 IoCopyCurrentIrpStackLocationToNext (Irp
);
784 /* set completion routine */
785 IoSetCompletionRoutine(Irp
, KbdHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
786 Irp
->IoStatus
.Status
= 0;
789 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
790 if (Status
== STATUS_PENDING
)
792 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
793 Status
= Irp
->IoStatus
.Status
;
796 if (!NT_SUCCESS(Status
))
799 Irp
->IoStatus
.Status
= Status
;
800 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
804 /* lets start the device */
805 Status
= KbdHid_StartDevice(DeviceObject
);
806 DPRINT("KbdHid_StartDevice %x\n", Status
);
808 /* complete request */
809 Irp
->IoStatus
.Status
= Status
;
810 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
817 /* skip irp stack location */
818 IoSkipCurrentIrpStackLocation(Irp
);
820 /* dispatch to lower device */
821 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
828 IN PDRIVER_OBJECT DriverObject
,
829 IN PDEVICE_OBJECT PhysicalDeviceObject
)
832 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
833 PKBDHID_DEVICE_EXTENSION DeviceExtension
;
836 /* create device object */
837 Status
= IoCreateDevice(DriverObject
, sizeof(KBDHID_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KEYBOARD
, 0, FALSE
, &DeviceObject
);
838 if (!NT_SUCCESS(Status
))
840 /* failed to create device object */
845 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
846 if (!NextDeviceObject
)
848 /* failed to attach */
849 IoDeleteDevice(DeviceObject
);
850 return STATUS_DEVICE_NOT_CONNECTED
;
853 /* get device extension */
854 DeviceExtension
= (PKBDHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
857 RtlZeroMemory(DeviceExtension
, sizeof(KBDHID_DEVICE_EXTENSION
));
859 /* init device extension */
860 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
861 KeInitializeEvent(&DeviceExtension
->ReadCompletionEvent
, NotificationEvent
, FALSE
);
863 /* init keyboard attributes */
864 DeviceExtension
->Attributes
.KeyboardIdentifier
.Type
= KEYBOARD_TYPE_UNKNOWN
;
865 DeviceExtension
->Attributes
.KeyboardIdentifier
.Subtype
= MICROSOFT_KBD_101_TYPE
;
866 DeviceExtension
->Attributes
.NumberOfFunctionKeys
= MICROSOFT_KBD_FUNC
;
867 DeviceExtension
->Attributes
.NumberOfIndicators
= 3; // caps, num lock, scroll lock
868 DeviceExtension
->Attributes
.NumberOfKeysTotal
= 101;
869 DeviceExtension
->Attributes
.InputDataQueueLength
= 1;
870 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Rate
= KEYBOARD_TYPEMATIC_RATE_MINIMUM
;
871 DeviceExtension
->Attributes
.KeyRepeatMinimum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MINIMUM
;
872 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Rate
= KEYBOARD_TYPEMATIC_RATE_DEFAULT
;
873 DeviceExtension
->Attributes
.KeyRepeatMaximum
.Delay
= KEYBOARD_TYPEMATIC_DELAY_MAXIMUM
;
876 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
878 /* FIXME handle allocation error */
879 ASSERT(DeviceExtension
->Irp
);
881 /* set power state to D0 */
882 State
.DeviceState
= PowerDeviceD0
;
883 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
885 /* init device object */
886 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
887 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
889 /* completed successfully */
890 return STATUS_SUCCESS
;
896 IN PDRIVER_OBJECT DriverObject
)
905 IN PDRIVER_OBJECT DriverObject
,
906 IN PUNICODE_STRING RegPath
)
908 /* initialize driver object */
909 DriverObject
->DriverUnload
= KbdHid_Unload
;
910 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
911 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = KbdHid_Create
;
912 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = KbdHid_Close
;
913 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = KbdHid_Flush
;
914 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = KbdHid_DeviceControl
;
915 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = KbdHid_InternalDeviceControl
;
916 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KbdHid_Power
;
917 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KbdHid_Pnp
;
918 DriverObject
->DriverUnload
= KbdHid_Unload
;
919 DriverObject
->DriverExtension
->AddDevice
= KbdHid_AddDevice
;
922 return STATUS_SUCCESS
;