[HIDPARSE]
[reactos.git] / drivers / hid / kbdhid / kbdhid.c
1 /*
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
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #include "kbdhid.h"
12
13 VOID
14 KbdHid_DispatchInputData(
15 IN PKBDHID_DEVICE_EXTENSION DeviceExtension,
16 IN PKEYBOARD_INPUT_DATA InputData)
17 {
18 KIRQL OldIrql;
19 ULONG InputDataConsumed;
20
21 if (!DeviceExtension->ClassService)
22 return;
23
24 /* sanity check */
25 ASSERT(DeviceExtension->ClassService);
26 ASSERT(DeviceExtension->ClassDeviceObject);
27
28 /* raise irql */
29 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
30
31 /* dispatch input data */
32 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + 1, &InputDataConsumed);
33
34 /* lower irql to previous level */
35 KeLowerIrql(OldIrql);
36 }
37
38 BOOLEAN
39 NTAPI
40 KbdHid_InsertScanCodes(
41 IN PVOID Context,
42 IN PCHAR NewScanCodes,
43 IN ULONG Length)
44 {
45 //KEYBOARD_INPUT_DATA InputData;
46 ULONG Index;
47
48 for(Index = 0; Index < Length; Index++)
49 {
50 DPRINT1("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index, NewScanCodes[Index] & 0xFF);
51 //
52 // TODO: set up input data
53 //
54 //KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
55 }
56
57 //
58 // done
59 //
60 return TRUE;
61 }
62
63
64 NTSTATUS
65 NTAPI
66 KbdHid_ReadCompletion(
67 IN PDEVICE_OBJECT DeviceObject,
68 IN PIRP Irp,
69 IN PVOID Context)
70 {
71 PKBDHID_DEVICE_EXTENSION DeviceExtension;
72 NTSTATUS Status;
73 ULONG ButtonLength;
74
75 /* get device extension */
76 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
77
78 if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
79 Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
80 Irp->IoStatus.Status == STATUS_CANCELLED ||
81 DeviceExtension->StopReadReport)
82 {
83 /* failed to read or should be stopped*/
84 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
85
86 /* report no longer active */
87 DeviceExtension->ReadReportActive = FALSE;
88
89 /* request stopping of the report cycle */
90 DeviceExtension->StopReadReport = FALSE;
91
92 /* signal completion event */
93 KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
94 return STATUS_MORE_PROCESSING_REQUIRED;
95 }
96
97 //
98 // print out raw report
99 //
100 ASSERT(DeviceExtension->ReportLength >= 9);
101 DPRINT1("[KBDHID] ReadCompletion %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DeviceExtension->Report[0], DeviceExtension->Report[1], DeviceExtension->Report[2],
102 DeviceExtension->Report[3], DeviceExtension->Report[4], DeviceExtension->Report[5],
103 DeviceExtension->Report[6], DeviceExtension->Report[7], DeviceExtension->Report[8]);
104
105
106 /* get current usages */
107 ButtonLength = DeviceExtension->UsageListLength;
108 Status = HidP_GetUsagesEx(HidP_Input, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &ButtonLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
109 ASSERT(Status == HIDP_STATUS_SUCCESS);
110
111 /* FIXME check if needs mapping */
112
113 /* get usage difference */
114 Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
115 ASSERT(Status == HIDP_STATUS_SUCCESS);
116
117 /* replace previous usage list with current list */
118 RtlMoveMemory(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength);
119
120 /* translate break usage list */
121 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->BreakUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Break, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
122 ASSERT(Status == HIDP_STATUS_SUCCESS);
123
124 /* translate new usage list */
125 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Make, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
126 ASSERT(Status == HIDP_STATUS_SUCCESS);
127
128 /* re-init read */
129 KbdHid_InitiateRead(DeviceExtension);
130
131 /* stop completion */
132 return STATUS_MORE_PROCESSING_REQUIRED;
133 }
134
135 NTSTATUS
136 KbdHid_InitiateRead(
137 IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
138 {
139 PIO_STACK_LOCATION IoStack;
140 NTSTATUS Status;
141
142 /* re-use irp */
143 IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
144
145 /* init irp */
146 DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
147
148 /* get next stack location */
149 IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
150
151 /* init stack location */
152 IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
153 IoStack->Parameters.Read.Key = 0;
154 IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
155 IoStack->MajorFunction = IRP_MJ_READ;
156 IoStack->FileObject = DeviceExtension->FileObject;
157
158 /* set completion routine */
159 IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
160
161 /* read is active */
162 DeviceExtension->ReadReportActive = TRUE;
163
164 /* start the read */
165 Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
166
167 /* done */
168 return Status;
169 }
170
171 NTSTATUS
172 NTAPI
173 KbdHid_CreateCompletion(
174 IN PDEVICE_OBJECT DeviceObject,
175 IN PIRP Irp,
176 IN PVOID Context)
177 {
178 KeSetEvent((PKEVENT)Context, 0, FALSE);
179 return STATUS_MORE_PROCESSING_REQUIRED;
180 }
181
182
183 NTSTATUS
184 NTAPI
185 KbdHid_Create(
186 IN PDEVICE_OBJECT DeviceObject,
187 IN PIRP Irp)
188 {
189 PIO_STACK_LOCATION IoStack;
190 NTSTATUS Status;
191 KEVENT Event;
192 PKBDHID_DEVICE_EXTENSION DeviceExtension;
193
194 DPRINT1("[KBDHID]: IRP_MJ_CREATE\n");
195
196 /* get device extension */
197 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
198
199 /* get stack location */
200 IoStack = IoGetCurrentIrpStackLocation(Irp);
201
202 /* copy stack location to next */
203 IoCopyCurrentIrpStackLocationToNext(Irp);
204
205 /* init event */
206 KeInitializeEvent(&Event, NotificationEvent, FALSE);
207
208 /* prepare irp */
209 IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
210
211 /* call lower driver */
212 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
213 if (Status == STATUS_PENDING)
214 {
215 /* request pending */
216 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
217 }
218
219 /* check for success */
220 if (!NT_SUCCESS(Status))
221 {
222 /* failed */
223 Irp->IoStatus.Status = Status;
224 IoCompleteRequest(Irp, IO_NO_INCREMENT);
225 return Status;
226 }
227
228 /* is the driver already in use */
229 if (DeviceExtension->FileObject == NULL)
230 {
231 /* did the caller specify correct attributes */
232 ASSERT(IoStack->Parameters.Create.SecurityContext);
233 if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
234 {
235 /* store file object */
236 DeviceExtension->FileObject = IoStack->FileObject;
237
238 /* reset event */
239 KeResetEvent(&DeviceExtension->ReadCompletionEvent);
240
241 /* initiating read */
242 Status = KbdHid_InitiateRead(DeviceExtension);
243 DPRINT1("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
244 if (Status == STATUS_PENDING)
245 {
246 /* report irp is pending */
247 Status = STATUS_SUCCESS;
248 }
249 }
250 }
251
252 /* complete request */
253 Irp->IoStatus.Status = Status;
254 IoCompleteRequest(Irp, IO_NO_INCREMENT);
255 return Status;
256 }
257
258
259 NTSTATUS
260 NTAPI
261 KbdHid_Close(
262 IN PDEVICE_OBJECT DeviceObject,
263 IN PIRP Irp)
264 {
265 PKBDHID_DEVICE_EXTENSION DeviceExtension;
266
267 /* get device extension */
268 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
269
270 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
271
272 if (DeviceExtension->ReadReportActive)
273 {
274 /* request stopping of the report cycle */
275 DeviceExtension->StopReadReport = TRUE;
276
277 /* wait until the reports have been read */
278 KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
279
280 /* cancel irp */
281 IoCancelIrp(DeviceExtension->Irp);
282 }
283
284 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
285
286 /* remove file object */
287 DeviceExtension->FileObject = NULL;
288
289 /* skip location */
290 IoSkipCurrentIrpStackLocation(Irp);
291
292 /* pass irp to down the stack */
293 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
294 }
295
296 NTSTATUS
297 NTAPI
298 KbdHid_InternalDeviceControl(
299 IN PDEVICE_OBJECT DeviceObject,
300 IN PIRP Irp)
301 {
302 PIO_STACK_LOCATION IoStack;
303 PKBDHID_DEVICE_EXTENSION DeviceExtension;
304 PCONNECT_DATA Data;
305 PKEYBOARD_ATTRIBUTES Attributes;
306
307 /* get current stack location */
308 IoStack = IoGetCurrentIrpStackLocation(Irp);
309
310 DPRINT1("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
311
312 /* get device extension */
313 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
314
315 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES)
316 {
317 /* verify output buffer length */
318 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
319 {
320 /* invalid request */
321 DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
322 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
323 IoCompleteRequest(Irp, IO_NO_INCREMENT);
324 return STATUS_BUFFER_TOO_SMALL;
325 }
326
327 /* get output buffer */
328 Attributes = (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
329
330 /* copy attributes */
331 RtlCopyMemory(Attributes, &DeviceExtension->Attributes, sizeof(KEYBOARD_ATTRIBUTES));
332
333 /* complete request */
334 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
335 Irp->IoStatus.Status = STATUS_SUCCESS;
336 IoCompleteRequest(Irp, IO_NO_INCREMENT);
337 return STATUS_SUCCESS;
338 }
339 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_CONNECT)
340 {
341 /* verify input buffer length */
342 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
343 {
344 /* invalid request */
345 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
346 IoCompleteRequest(Irp, IO_NO_INCREMENT);
347 return STATUS_INVALID_PARAMETER;
348 }
349
350 /* is it already connected */
351 if (DeviceExtension->ClassService)
352 {
353 /* already connected */
354 Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
355 IoCompleteRequest(Irp, IO_NO_INCREMENT);
356 return STATUS_SHARING_VIOLATION;
357 }
358
359 /* get connect data */
360 Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
361
362 /* store connect details */
363 DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
364 DeviceExtension->ClassService = Data->ClassService;
365
366 /* completed successfully */
367 Irp->IoStatus.Status = STATUS_SUCCESS;
368 IoCompleteRequest(Irp, IO_NO_INCREMENT);
369 return STATUS_SUCCESS;
370 }
371 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISCONNECT)
372 {
373 /* not implemented */
374 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
375 IoCompleteRequest(Irp, IO_NO_INCREMENT);
376 return STATUS_NOT_IMPLEMENTED;
377 }
378 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_ENABLE)
379 {
380 /* not supported */
381 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
382 IoCompleteRequest(Irp, IO_NO_INCREMENT);
383 return STATUS_NOT_SUPPORTED;
384 }
385 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISABLE)
386 {
387 /* not supported */
388 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
389 IoCompleteRequest(Irp, IO_NO_INCREMENT);
390 return STATUS_NOT_SUPPORTED;
391 }
392 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATORS)
393 {
394 /* not implemented */
395 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATORS not implemented\n");
396 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
397 IoCompleteRequest(Irp, IO_NO_INCREMENT);
398 return STATUS_NOT_IMPLEMENTED;
399 }
400 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_TYPEMATIC)
401 {
402 /* not implemented */
403 DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n");
404 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
405 IoCompleteRequest(Irp, IO_NO_INCREMENT);
406 return STATUS_NOT_IMPLEMENTED;
407 }
408 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_INDICATORS)
409 {
410 /* not implemented */
411 DPRINT1("IOCTL_KEYBOARD_SET_INDICATORS not implemented\n");
412 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
413 IoCompleteRequest(Irp, IO_NO_INCREMENT);
414 return STATUS_NOT_IMPLEMENTED;
415 }
416 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_TYPEMATIC)
417 {
418 /* not implemented */
419 DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n");
420 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
421 IoCompleteRequest(Irp, IO_NO_INCREMENT);
422 return STATUS_NOT_IMPLEMENTED;
423 }
424 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION)
425 {
426 /* not implemented */
427 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
428 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
429 IoCompleteRequest(Irp, IO_NO_INCREMENT);
430 return STATUS_NOT_IMPLEMENTED;
431 }
432
433 /* unknown control code */
434 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
435 /* unknown request not supported */
436 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
437 IoCompleteRequest(Irp, IO_NO_INCREMENT);
438 return STATUS_NOT_SUPPORTED;
439 }
440
441 NTSTATUS
442 NTAPI
443 KbdHid_DeviceControl(
444 IN PDEVICE_OBJECT DeviceObject,
445 IN PIRP Irp)
446 {
447 PKBDHID_DEVICE_EXTENSION DeviceExtension;
448
449 /* get device extension */
450 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
451
452 /* skip stack location */
453 IoSkipCurrentIrpStackLocation(Irp);
454
455 /* pass and forget */
456 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
457 }
458
459 NTSTATUS
460 NTAPI
461 KbdHid_Power(
462 IN PDEVICE_OBJECT DeviceObject,
463 IN PIRP Irp)
464 {
465 UNIMPLEMENTED
466 return STATUS_NOT_IMPLEMENTED;
467 }
468
469 NTSTATUS
470 KbdHid_SubmitRequest(
471 PDEVICE_OBJECT DeviceObject,
472 ULONG IoControlCode,
473 ULONG InputBufferSize,
474 PVOID InputBuffer,
475 ULONG OutputBufferSize,
476 PVOID OutputBuffer)
477 {
478 KEVENT Event;
479 PKBDHID_DEVICE_EXTENSION DeviceExtension;
480 PIRP Irp;
481 NTSTATUS Status;
482 IO_STATUS_BLOCK IoStatus;
483
484 /* get device extension */
485 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
486
487 /* init event */
488 KeInitializeEvent(&Event, NotificationEvent, FALSE);
489
490 /* build request */
491 Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
492 if (!Irp)
493 {
494 /* no memory */
495 return STATUS_INSUFFICIENT_RESOURCES;
496 }
497
498 /* send request */
499 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
500 if (Status == STATUS_PENDING)
501 {
502 /* wait for request to complete */
503 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
504 Status = IoStatus.Status;
505 }
506
507 /* done */
508 return Status;
509 }
510
511 NTSTATUS
512 NTAPI
513 KbdHid_StartDevice(
514 IN PDEVICE_OBJECT DeviceObject)
515 {
516 NTSTATUS Status;
517 ULONG Buttons;
518 HID_COLLECTION_INFORMATION Information;
519 PHIDP_PREPARSED_DATA PreparsedData;
520 HIDP_CAPS Capabilities;
521 PKBDHID_DEVICE_EXTENSION DeviceExtension;
522 PUSAGE_AND_PAGE Buffer;
523
524 /* get device extension */
525 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
526
527 /* query collection information */
528 Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
529 if (!NT_SUCCESS(Status))
530 {
531 /* failed to query collection information */
532 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
533 return Status;
534 }
535
536 /* lets allocate space for preparsed data */
537 PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
538 if (!PreparsedData)
539 {
540 /* no memory */
541 DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
542 return STATUS_INSUFFICIENT_RESOURCES;
543 }
544
545 /* now obtain the preparsed data */
546 Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
547 if (!NT_SUCCESS(Status))
548 {
549 /* failed to get preparsed data */
550 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
551 ExFreePool(PreparsedData);
552 return Status;
553 }
554
555 /* lets get the caps */
556 Status = HidP_GetCaps(PreparsedData, &Capabilities);
557 if (Status != HIDP_STATUS_SUCCESS)
558 {
559 /* failed to get capabilities */
560 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
561 ExFreePool(PreparsedData);
562 return Status;
563 }
564
565 DPRINT1("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
566
567 /* init input report*/
568 DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
569 ASSERT(DeviceExtension->ReportLength);
570 DeviceExtension->Report = (PCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
571 ASSERT(DeviceExtension->Report);
572 RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
573
574 /* build mdl */
575 DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
576 ASSERT(DeviceExtension->ReportMDL);
577
578 /* init mdl */
579 MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
580
581 /* get max number of buttons */
582 Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_KEYBOARD, PreparsedData);
583 DPRINT1("[KBDHID] Buttons %lu\n", Buttons);
584 ASSERT(Buttons > 0);
585
586 /* now allocate an array for those buttons */
587 Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
588 if (!Buffer)
589 {
590 /* no memory */
591 ExFreePool(PreparsedData);
592 return STATUS_INSUFFICIENT_RESOURCES;
593 }
594
595 /* init usage lists */
596 RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
597 DeviceExtension->CurrentUsageList = Buffer;
598 Buffer += Buttons;
599 DeviceExtension->PreviousUsageList = Buffer;
600 Buffer += Buttons;
601 DeviceExtension->MakeUsageList = Buffer;
602 Buffer += Buttons;
603 DeviceExtension->BreakUsageList = Buffer;
604
605 //
606 // FIMXE: implement device hacks
607 //
608 // UsageMappings
609 // KeyboardTypeOverride
610 // KeyboardSubTypeOverride
611 // KeyboardNumberTotalKeysOverride
612 // KeyboardNumberFunctionKeysOverride
613 // KeyboardNumberIndicatorsOverride
614
615 /* store number of buttons */
616 DeviceExtension->UsageListLength = (USHORT)Buttons;
617
618 /* store preparsed data */
619 DeviceExtension->PreparsedData = PreparsedData;
620
621 /* completed successfully */
622 return STATUS_SUCCESS;
623 }
624
625 NTSTATUS
626 NTAPI
627 KbdHid_StartDeviceCompletion(
628 IN PDEVICE_OBJECT DeviceObject,
629 IN PIRP Irp,
630 IN PVOID Context)
631 {
632 KeSetEvent((PKEVENT)Context, 0, FALSE);
633 return STATUS_MORE_PROCESSING_REQUIRED;
634 }
635
636 NTSTATUS
637 NTAPI
638 KbdHid_Flush(
639 IN PDEVICE_OBJECT DeviceObject,
640 IN PIRP Irp)
641 {
642 PIO_STACK_LOCATION IoStack;
643 PKBDHID_DEVICE_EXTENSION DeviceExtension;
644
645 /* get device extension */
646 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
647
648 /* skip current stack location */
649 IoSkipCurrentIrpStackLocation(Irp);
650
651 /* get next stack location */
652 IoStack = IoGetNextIrpStackLocation(Irp);
653
654 /* change request to hid flush queue request */
655 IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
656 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
657
658 /* call device */
659 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
660 }
661
662 NTSTATUS
663 NTAPI
664 KbdHid_Pnp(
665 IN PDEVICE_OBJECT DeviceObject,
666 IN PIRP Irp)
667 {
668 PIO_STACK_LOCATION IoStack;
669 KEVENT Event;
670 NTSTATUS Status;
671 PKBDHID_DEVICE_EXTENSION DeviceExtension;
672
673 /* get device extension */
674 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
675
676 /* get current irp stack */
677 IoStack = IoGetCurrentIrpStackLocation(Irp);
678 DPRINT1("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
679
680 if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE)
681 {
682 /* indicate success */
683 Irp->IoStatus.Status = STATUS_SUCCESS;
684
685 /* skip irp stack location */
686 IoSkipCurrentIrpStackLocation(Irp);
687
688 /* dispatch to lower device */
689 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
690 }
691 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
692 {
693 /* FIXME synchronization */
694
695 /* cancel irp */
696 IoCancelIrp(DeviceExtension->Irp);
697
698 /* indicate success */
699 Irp->IoStatus.Status = STATUS_SUCCESS;
700
701 /* skip irp stack location */
702 IoSkipCurrentIrpStackLocation(Irp);
703
704 /* dispatch to lower device */
705 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
706
707 IoFreeIrp(DeviceExtension->Irp);
708 IoDetachDevice(DeviceExtension->NextDeviceObject);
709 IoDeleteDevice(DeviceObject);
710 return Status;
711 }
712 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
713 {
714 /* init event */
715 KeInitializeEvent(&Event, NotificationEvent, FALSE);
716
717 /* copy stack location */
718 IoCopyCurrentIrpStackLocationToNext (Irp);
719
720 /* set completion routine */
721 IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
722 Irp->IoStatus.Status = 0;
723
724 /* pass request */
725 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
726 if (Status == STATUS_PENDING)
727 {
728 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
729 Status = Irp->IoStatus.Status;
730 }
731
732 if (!NT_SUCCESS(Status))
733 {
734 /* failed */
735 Irp->IoStatus.Status = Status;
736 IoCompleteRequest(Irp, IO_NO_INCREMENT);
737 return Status;
738 }
739
740 /* lets start the device */
741 Status = KbdHid_StartDevice(DeviceObject);
742 DPRINT1("KbdHid_StartDevice %x\n", Status);
743
744 /* complete request */
745 Irp->IoStatus.Status = Status;
746 IoCompleteRequest(Irp, IO_NO_INCREMENT);
747
748 /* done */
749 return Status;
750 }
751 else
752 {
753 /* skip irp stack location */
754 IoSkipCurrentIrpStackLocation(Irp);
755
756 /* dispatch to lower device */
757 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
758 }
759 }
760
761 NTSTATUS
762 NTAPI
763 KbdHid_AddDevice(
764 IN PDRIVER_OBJECT DriverObject,
765 IN PDEVICE_OBJECT PhysicalDeviceObject)
766 {
767 NTSTATUS Status;
768 PDEVICE_OBJECT DeviceObject, NextDeviceObject;
769 PKBDHID_DEVICE_EXTENSION DeviceExtension;
770 POWER_STATE State;
771
772 /* create device object */
773 Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
774 if (!NT_SUCCESS(Status))
775 {
776 /* failed to create device object */
777 return Status;
778 }
779
780 /* now attach it */
781 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
782 if (!NextDeviceObject)
783 {
784 /* failed to attach */
785 IoDeleteDevice(DeviceObject);
786 return STATUS_DEVICE_NOT_CONNECTED;
787 }
788
789 /* get device extension */
790 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
791
792 /* zero extension */
793 RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
794
795 /* init device extension */
796 DeviceExtension->NextDeviceObject = NextDeviceObject;
797 KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
798
799 /* init keyboard attributes */
800 DeviceExtension->Attributes.KeyboardIdentifier.Type = KEYBOARD_TYPE_UNKNOWN;
801 DeviceExtension->Attributes.KeyboardIdentifier.Subtype = MICROSOFT_KBD_101_TYPE;
802 DeviceExtension->Attributes.NumberOfFunctionKeys = MICROSOFT_KBD_FUNC;
803 DeviceExtension->Attributes.NumberOfIndicators = 3; // caps, num lock, scroll lock
804 DeviceExtension->Attributes.NumberOfKeysTotal = 101;
805 DeviceExtension->Attributes.InputDataQueueLength = 1;
806 DeviceExtension->Attributes.KeyRepeatMinimum.Rate = KEYBOARD_TYPEMATIC_RATE_MINIMUM;
807 DeviceExtension->Attributes.KeyRepeatMinimum.Delay = KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
808 DeviceExtension->Attributes.KeyRepeatMaximum.Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
809 DeviceExtension->Attributes.KeyRepeatMaximum.Delay = KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
810
811 /* allocate irp */
812 DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
813
814 /* FIXME handle allocation error */
815 ASSERT(DeviceExtension->Irp);
816
817 /* set power state to D0 */
818 State.DeviceState = PowerDeviceD0;
819 PoSetPowerState(DeviceObject, DevicePowerState, State);
820
821 /* init device object */
822 DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
823 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
824
825 /* completed successfully */
826 return STATUS_SUCCESS;
827 }
828
829 VOID
830 NTAPI
831 KbdHid_Unload(
832 IN PDRIVER_OBJECT DriverObject)
833 {
834 UNIMPLEMENTED
835 }
836
837
838 NTSTATUS
839 NTAPI
840 DriverEntry(
841 IN PDRIVER_OBJECT DriverObject,
842 IN PUNICODE_STRING RegPath)
843 {
844 /* initialize driver object */
845 DriverObject->DriverUnload = KbdHid_Unload;
846 DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
847 DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create;
848 DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close;
849 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush;
850 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl;
851 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl;
852 DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power;
853 DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp;
854 DriverObject->DriverUnload = KbdHid_Unload;
855 DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
856
857 /* done */
858 return STATUS_SUCCESS;
859 }