[KBDHID][HIDPARSER]
[reactos.git] / reactos / 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 PKBDHID_DEVICE_EXTENSION DeviceExtension;
48 CHAR Prefix = 0;
49
50 /* get device extension */
51 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
52
53 for(Index = 0; Index < Length; Index++)
54 {
55 DPRINT("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index, NewScanCodes[Index] & 0xFF);
56
57 /* check if this is E0 or E1 prefix */
58 if (NewScanCodes[Index] == (CHAR)0xE0 || NewScanCodes[Index] == (CHAR)0xE1)
59 {
60 Prefix = NewScanCodes[Index];
61 continue;
62 }
63
64 /* init input data */
65 RtlZeroMemory(&InputData, sizeof(KEYBOARD_INPUT_DATA));
66
67 /* use keyboard unit id */
68 InputData.UnitId = DeviceExtension->KeyboardTypematic.UnitId;
69
70 if (NewScanCodes[Index] & 0x80)
71 {
72 /* scan codes with 0x80 flag are a key break */
73 InputData.Flags |= KEY_BREAK;
74 }
75
76 /* set a prefix if needed */
77 if (Prefix)
78 {
79 InputData.Flags |= (Prefix == (CHAR)0xE0 ? KEY_E0 : KEY_E1);
80 Prefix = 0;
81 }
82
83 /* store key code */
84 InputData.MakeCode = NewScanCodes[Index] & 0x7F;
85
86 /* dispatch scan codes */
87 KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
88 }
89
90 /* done */
91 return TRUE;
92 }
93
94
95 NTSTATUS
96 NTAPI
97 KbdHid_ReadCompletion(
98 IN PDEVICE_OBJECT DeviceObject,
99 IN PIRP Irp,
100 IN PVOID Context)
101 {
102 PKBDHID_DEVICE_EXTENSION DeviceExtension;
103 NTSTATUS Status;
104 ULONG ButtonLength;
105
106 /* get device extension */
107 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
108
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)
113 {
114 /* failed to read or should be stopped*/
115 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
116
117 /* report no longer active */
118 DeviceExtension->ReadReportActive = FALSE;
119
120 /* request stopping of the report cycle */
121 DeviceExtension->StopReadReport = FALSE;
122
123 /* signal completion event */
124 KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
125 return STATUS_MORE_PROCESSING_REQUIRED;
126 }
127
128 //
129 // print out raw report
130 //
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]);
135
136
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);
141
142 /* FIXME check if needs mapping */
143
144 /* get usage difference */
145 Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
146 ASSERT(Status == HIDP_STATUS_SUCCESS);
147
148 /* replace previous usage list with current list */
149 RtlMoveMemory(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength);
150
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);
154
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);
158
159 /* re-init read */
160 KbdHid_InitiateRead(DeviceExtension);
161
162 /* stop completion */
163 return STATUS_MORE_PROCESSING_REQUIRED;
164 }
165
166 NTSTATUS
167 KbdHid_InitiateRead(
168 IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
169 {
170 PIO_STACK_LOCATION IoStack;
171 NTSTATUS Status;
172
173 /* re-use irp */
174 IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
175
176 /* init irp */
177 DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
178
179 /* get next stack location */
180 IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
181
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;
188
189 /* set completion routine */
190 IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
191
192 /* read is active */
193 DeviceExtension->ReadReportActive = TRUE;
194
195 /* start the read */
196 Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
197
198 /* done */
199 return Status;
200 }
201
202 NTSTATUS
203 NTAPI
204 KbdHid_CreateCompletion(
205 IN PDEVICE_OBJECT DeviceObject,
206 IN PIRP Irp,
207 IN PVOID Context)
208 {
209 KeSetEvent((PKEVENT)Context, 0, FALSE);
210 return STATUS_MORE_PROCESSING_REQUIRED;
211 }
212
213
214 NTSTATUS
215 NTAPI
216 KbdHid_Create(
217 IN PDEVICE_OBJECT DeviceObject,
218 IN PIRP Irp)
219 {
220 PIO_STACK_LOCATION IoStack;
221 NTSTATUS Status;
222 KEVENT Event;
223 PKBDHID_DEVICE_EXTENSION DeviceExtension;
224
225 DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
226
227 /* get device extension */
228 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
229
230 /* get stack location */
231 IoStack = IoGetCurrentIrpStackLocation(Irp);
232
233 /* copy stack location to next */
234 IoCopyCurrentIrpStackLocationToNext(Irp);
235
236 /* init event */
237 KeInitializeEvent(&Event, NotificationEvent, FALSE);
238
239 /* prepare irp */
240 IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
241
242 /* call lower driver */
243 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
244 if (Status == STATUS_PENDING)
245 {
246 /* request pending */
247 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
248 }
249
250 /* check for success */
251 if (!NT_SUCCESS(Status))
252 {
253 /* failed */
254 Irp->IoStatus.Status = Status;
255 IoCompleteRequest(Irp, IO_NO_INCREMENT);
256 return Status;
257 }
258
259 /* is the driver already in use */
260 if (DeviceExtension->FileObject == NULL)
261 {
262 /* did the caller specify correct attributes */
263 ASSERT(IoStack->Parameters.Create.SecurityContext);
264 if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
265 {
266 /* store file object */
267 DeviceExtension->FileObject = IoStack->FileObject;
268
269 /* reset event */
270 KeResetEvent(&DeviceExtension->ReadCompletionEvent);
271
272 /* initiating read */
273 Status = KbdHid_InitiateRead(DeviceExtension);
274 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
275 if (Status == STATUS_PENDING)
276 {
277 /* report irp is pending */
278 Status = STATUS_SUCCESS;
279 }
280 }
281 }
282
283 /* complete request */
284 Irp->IoStatus.Status = Status;
285 IoCompleteRequest(Irp, IO_NO_INCREMENT);
286 return Status;
287 }
288
289
290 NTSTATUS
291 NTAPI
292 KbdHid_Close(
293 IN PDEVICE_OBJECT DeviceObject,
294 IN PIRP Irp)
295 {
296 PKBDHID_DEVICE_EXTENSION DeviceExtension;
297
298 /* get device extension */
299 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
300
301 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
302
303 if (DeviceExtension->ReadReportActive)
304 {
305 /* request stopping of the report cycle */
306 DeviceExtension->StopReadReport = TRUE;
307
308 /* wait until the reports have been read */
309 KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
310
311 /* cancel irp */
312 IoCancelIrp(DeviceExtension->Irp);
313 }
314
315 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
316
317 /* remove file object */
318 DeviceExtension->FileObject = NULL;
319
320 /* skip location */
321 IoSkipCurrentIrpStackLocation(Irp);
322
323 /* pass irp to down the stack */
324 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
325 }
326
327 NTSTATUS
328 NTAPI
329 KbdHid_InternalDeviceControl(
330 IN PDEVICE_OBJECT DeviceObject,
331 IN PIRP Irp)
332 {
333 PIO_STACK_LOCATION IoStack;
334 PKBDHID_DEVICE_EXTENSION DeviceExtension;
335 PCONNECT_DATA Data;
336 PKEYBOARD_ATTRIBUTES Attributes;
337
338 /* get current stack location */
339 IoStack = IoGetCurrentIrpStackLocation(Irp);
340
341 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
342
343 /* get device extension */
344 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
345
346 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES)
347 {
348 /* verify output buffer length */
349 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
350 {
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;
356 }
357
358 /* get output buffer */
359 Attributes = (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
360
361 /* copy attributes */
362 RtlCopyMemory(Attributes, &DeviceExtension->Attributes, sizeof(KEYBOARD_ATTRIBUTES));
363
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;
369 }
370 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_CONNECT)
371 {
372 /* verify input buffer length */
373 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
374 {
375 /* invalid request */
376 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
377 IoCompleteRequest(Irp, IO_NO_INCREMENT);
378 return STATUS_INVALID_PARAMETER;
379 }
380
381 /* is it already connected */
382 if (DeviceExtension->ClassService)
383 {
384 /* already connected */
385 Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
386 IoCompleteRequest(Irp, IO_NO_INCREMENT);
387 return STATUS_SHARING_VIOLATION;
388 }
389
390 /* get connect data */
391 Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
392
393 /* store connect details */
394 DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
395 DeviceExtension->ClassService = Data->ClassService;
396
397 /* completed successfully */
398 Irp->IoStatus.Status = STATUS_SUCCESS;
399 IoCompleteRequest(Irp, IO_NO_INCREMENT);
400 return STATUS_SUCCESS;
401 }
402 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISCONNECT)
403 {
404 /* not implemented */
405 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
406 IoCompleteRequest(Irp, IO_NO_INCREMENT);
407 return STATUS_NOT_IMPLEMENTED;
408 }
409 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_ENABLE)
410 {
411 /* not supported */
412 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
413 IoCompleteRequest(Irp, IO_NO_INCREMENT);
414 return STATUS_NOT_SUPPORTED;
415 }
416 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISABLE)
417 {
418 /* not supported */
419 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
420 IoCompleteRequest(Irp, IO_NO_INCREMENT);
421 return STATUS_NOT_SUPPORTED;
422 }
423 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATORS)
424 {
425 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
426 {
427 /* invalid parameter */
428 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
429 IoCompleteRequest(Irp, IO_NO_INCREMENT);
430 return STATUS_INVALID_PARAMETER;
431 }
432
433 /* copy indicators */
434 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &DeviceExtension->KeyboardIndicator, sizeof(KEYBOARD_INDICATOR_PARAMETERS));
435
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;
441 }
442 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_TYPEMATIC)
443 {
444 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS))
445 {
446 /* invalid parameter */
447 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
448 IoCompleteRequest(Irp, IO_NO_INCREMENT);
449 return STATUS_INVALID_PARAMETER;
450 }
451
452 /* copy indicators */
453 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &DeviceExtension->KeyboardTypematic, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));
454
455 /* done */
456 Irp->IoStatus.Status = STATUS_SUCCESS;
457 Irp->IoStatus.Information = sizeof(KEYBOARD_TYPEMATIC_PARAMETERS);
458 IoCompleteRequest(Irp, IO_NO_INCREMENT);
459 return STATUS_SUCCESS;
460 }
461 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_INDICATORS)
462 {
463 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
464 {
465 /* invalid parameter */
466 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
467 IoCompleteRequest(Irp, IO_NO_INCREMENT);
468 return STATUS_INVALID_PARAMETER;
469 }
470
471 /* copy indicators */
472 RtlCopyMemory(&DeviceExtension->KeyboardIndicator, Irp->AssociatedIrp.SystemBuffer, sizeof(KEYBOARD_INDICATOR_PARAMETERS));
473
474 /* done */
475 Irp->IoStatus.Status = STATUS_SUCCESS;
476 Irp->IoStatus.Information = 0;
477 IoCompleteRequest(Irp, IO_NO_INCREMENT);
478 return STATUS_SUCCESS;
479 }
480 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_TYPEMATIC)
481 {
482 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS))
483 {
484 /* invalid parameter */
485 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
486 IoCompleteRequest(Irp, IO_NO_INCREMENT);
487 return STATUS_INVALID_PARAMETER;
488 }
489
490 /* copy indicators */
491 RtlCopyMemory(&DeviceExtension->KeyboardTypematic, Irp->AssociatedIrp.SystemBuffer, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));
492
493 /* done */
494 Irp->IoStatus.Status = STATUS_SUCCESS;
495 Irp->IoStatus.Information = 0;
496 IoCompleteRequest(Irp, IO_NO_INCREMENT);
497 return STATUS_SUCCESS;
498 }
499 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION)
500 {
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;
506 }
507
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;
514 }
515
516 NTSTATUS
517 NTAPI
518 KbdHid_DeviceControl(
519 IN PDEVICE_OBJECT DeviceObject,
520 IN PIRP Irp)
521 {
522 PKBDHID_DEVICE_EXTENSION DeviceExtension;
523
524 /* get device extension */
525 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
526
527 /* skip stack location */
528 IoSkipCurrentIrpStackLocation(Irp);
529
530 /* pass and forget */
531 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
532 }
533
534 NTSTATUS
535 NTAPI
536 KbdHid_Power(
537 IN PDEVICE_OBJECT DeviceObject,
538 IN PIRP Irp)
539 {
540 UNIMPLEMENTED
541 return STATUS_NOT_IMPLEMENTED;
542 }
543
544 NTSTATUS
545 KbdHid_SubmitRequest(
546 PDEVICE_OBJECT DeviceObject,
547 ULONG IoControlCode,
548 ULONG InputBufferSize,
549 PVOID InputBuffer,
550 ULONG OutputBufferSize,
551 PVOID OutputBuffer)
552 {
553 KEVENT Event;
554 PKBDHID_DEVICE_EXTENSION DeviceExtension;
555 PIRP Irp;
556 NTSTATUS Status;
557 IO_STATUS_BLOCK IoStatus;
558
559 /* get device extension */
560 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
561
562 /* init event */
563 KeInitializeEvent(&Event, NotificationEvent, FALSE);
564
565 /* build request */
566 Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
567 if (!Irp)
568 {
569 /* no memory */
570 return STATUS_INSUFFICIENT_RESOURCES;
571 }
572
573 /* send request */
574 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
575 if (Status == STATUS_PENDING)
576 {
577 /* wait for request to complete */
578 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
579 Status = IoStatus.Status;
580 }
581
582 /* done */
583 return Status;
584 }
585
586 NTSTATUS
587 NTAPI
588 KbdHid_StartDevice(
589 IN PDEVICE_OBJECT DeviceObject)
590 {
591 NTSTATUS Status;
592 ULONG Buttons;
593 HID_COLLECTION_INFORMATION Information;
594 PHIDP_PREPARSED_DATA PreparsedData;
595 HIDP_CAPS Capabilities;
596 PKBDHID_DEVICE_EXTENSION DeviceExtension;
597 PUSAGE_AND_PAGE Buffer;
598
599 /* get device extension */
600 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
601
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))
605 {
606 /* failed to query collection information */
607 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
608 return Status;
609 }
610
611 /* lets allocate space for preparsed data */
612 PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
613 if (!PreparsedData)
614 {
615 /* no memory */
616 DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
617 return STATUS_INSUFFICIENT_RESOURCES;
618 }
619
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))
623 {
624 /* failed to get preparsed data */
625 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
626 ExFreePool(PreparsedData);
627 return Status;
628 }
629
630 /* lets get the caps */
631 Status = HidP_GetCaps(PreparsedData, &Capabilities);
632 if (Status != HIDP_STATUS_SUCCESS)
633 {
634 /* failed to get capabilities */
635 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
636 ExFreePool(PreparsedData);
637 return Status;
638 }
639
640 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
641
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);
648
649 /* build mdl */
650 DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
651 ASSERT(DeviceExtension->ReportMDL);
652
653 /* init mdl */
654 MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
655
656 /* get max number of buttons */
657 Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_KEYBOARD, PreparsedData);
658 DPRINT("[KBDHID] Buttons %lu\n", Buttons);
659 ASSERT(Buttons > 0);
660
661 /* now allocate an array for those buttons */
662 Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
663 if (!Buffer)
664 {
665 /* no memory */
666 ExFreePool(PreparsedData);
667 return STATUS_INSUFFICIENT_RESOURCES;
668 }
669
670 /* init usage lists */
671 RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
672 DeviceExtension->CurrentUsageList = Buffer;
673 Buffer += Buttons;
674 DeviceExtension->PreviousUsageList = Buffer;
675 Buffer += Buttons;
676 DeviceExtension->MakeUsageList = Buffer;
677 Buffer += Buttons;
678 DeviceExtension->BreakUsageList = Buffer;
679
680 //
681 // FIMXE: implement device hacks
682 //
683 // UsageMappings
684 // KeyboardTypeOverride
685 // KeyboardSubTypeOverride
686 // KeyboardNumberTotalKeysOverride
687 // KeyboardNumberFunctionKeysOverride
688 // KeyboardNumberIndicatorsOverride
689
690 /* store number of buttons */
691 DeviceExtension->UsageListLength = (USHORT)Buttons;
692
693 /* store preparsed data */
694 DeviceExtension->PreparsedData = PreparsedData;
695
696 /* completed successfully */
697 return STATUS_SUCCESS;
698 }
699
700 NTSTATUS
701 NTAPI
702 KbdHid_StartDeviceCompletion(
703 IN PDEVICE_OBJECT DeviceObject,
704 IN PIRP Irp,
705 IN PVOID Context)
706 {
707 KeSetEvent((PKEVENT)Context, 0, FALSE);
708 return STATUS_MORE_PROCESSING_REQUIRED;
709 }
710
711 NTSTATUS
712 NTAPI
713 KbdHid_Flush(
714 IN PDEVICE_OBJECT DeviceObject,
715 IN PIRP Irp)
716 {
717 PIO_STACK_LOCATION IoStack;
718 PKBDHID_DEVICE_EXTENSION DeviceExtension;
719
720 /* get device extension */
721 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
722
723 /* skip current stack location */
724 IoSkipCurrentIrpStackLocation(Irp);
725
726 /* get next stack location */
727 IoStack = IoGetNextIrpStackLocation(Irp);
728
729 /* change request to hid flush queue request */
730 IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
731 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
732
733 /* call device */
734 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
735 }
736
737 NTSTATUS
738 NTAPI
739 KbdHid_Pnp(
740 IN PDEVICE_OBJECT DeviceObject,
741 IN PIRP Irp)
742 {
743 PIO_STACK_LOCATION IoStack;
744 KEVENT Event;
745 NTSTATUS Status;
746 PKBDHID_DEVICE_EXTENSION DeviceExtension;
747
748 /* get device extension */
749 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
750
751 /* get current irp stack */
752 IoStack = IoGetCurrentIrpStackLocation(Irp);
753 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
754
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)
760 {
761 /* indicate success */
762 Irp->IoStatus.Status = STATUS_SUCCESS;
763
764 /* skip irp stack location */
765 IoSkipCurrentIrpStackLocation(Irp);
766
767 /* dispatch to lower device */
768 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
769 }
770 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
771 {
772 /* FIXME synchronization */
773
774 /* cancel irp */
775 IoCancelIrp(DeviceExtension->Irp);
776
777 /* indicate success */
778 Irp->IoStatus.Status = STATUS_SUCCESS;
779
780 /* skip irp stack location */
781 IoSkipCurrentIrpStackLocation(Irp);
782
783 /* dispatch to lower device */
784 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
785
786 IoFreeIrp(DeviceExtension->Irp);
787 IoDetachDevice(DeviceExtension->NextDeviceObject);
788 IoDeleteDevice(DeviceObject);
789 return Status;
790 }
791 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
792 {
793 /* init event */
794 KeInitializeEvent(&Event, NotificationEvent, FALSE);
795
796 /* copy stack location */
797 IoCopyCurrentIrpStackLocationToNext (Irp);
798
799 /* set completion routine */
800 IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
801 Irp->IoStatus.Status = 0;
802
803 /* pass request */
804 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
805 if (Status == STATUS_PENDING)
806 {
807 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
808 Status = Irp->IoStatus.Status;
809 }
810
811 if (!NT_SUCCESS(Status))
812 {
813 /* failed */
814 Irp->IoStatus.Status = Status;
815 IoCompleteRequest(Irp, IO_NO_INCREMENT);
816 return Status;
817 }
818
819 /* lets start the device */
820 Status = KbdHid_StartDevice(DeviceObject);
821 DPRINT("KbdHid_StartDevice %x\n", Status);
822
823 /* complete request */
824 Irp->IoStatus.Status = Status;
825 IoCompleteRequest(Irp, IO_NO_INCREMENT);
826
827 /* done */
828 return Status;
829 }
830 else
831 {
832 /* skip irp stack location */
833 IoSkipCurrentIrpStackLocation(Irp);
834
835 /* dispatch to lower device */
836 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
837 }
838 }
839
840 NTSTATUS
841 NTAPI
842 KbdHid_AddDevice(
843 IN PDRIVER_OBJECT DriverObject,
844 IN PDEVICE_OBJECT PhysicalDeviceObject)
845 {
846 NTSTATUS Status;
847 PDEVICE_OBJECT DeviceObject, NextDeviceObject;
848 PKBDHID_DEVICE_EXTENSION DeviceExtension;
849 POWER_STATE State;
850
851 /* create device object */
852 Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
853 if (!NT_SUCCESS(Status))
854 {
855 /* failed to create device object */
856 return Status;
857 }
858
859 /* now attach it */
860 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
861 if (!NextDeviceObject)
862 {
863 /* failed to attach */
864 IoDeleteDevice(DeviceObject);
865 return STATUS_DEVICE_NOT_CONNECTED;
866 }
867
868 /* get device extension */
869 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
870
871 /* zero extension */
872 RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
873
874 /* init device extension */
875 DeviceExtension->NextDeviceObject = NextDeviceObject;
876 KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
877
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;
889
890 /* allocate irp */
891 DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
892
893 /* FIXME handle allocation error */
894 ASSERT(DeviceExtension->Irp);
895
896 /* set power state to D0 */
897 State.DeviceState = PowerDeviceD0;
898 PoSetPowerState(DeviceObject, DevicePowerState, State);
899
900 /* init device object */
901 DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
902 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
903
904 /* completed successfully */
905 return STATUS_SUCCESS;
906 }
907
908 VOID
909 NTAPI
910 KbdHid_Unload(
911 IN PDRIVER_OBJECT DriverObject)
912 {
913 UNIMPLEMENTED
914 }
915
916
917 NTSTATUS
918 NTAPI
919 DriverEntry(
920 IN PDRIVER_OBJECT DriverObject,
921 IN PUNICODE_STRING RegPath)
922 {
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;
935
936 /* done */
937 return STATUS_SUCCESS;
938 }