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