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