[USB-BRINGUP]
[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 IN ULONG InputDataLength)
18 {
19 KIRQL OldIrql;
20 ULONG InputDataConsumed;
21
22 if (!DeviceExtension->ClassService)
23 return;
24
25 /* sanity check */
26 ASSERT(DeviceExtension->ClassService);
27 ASSERT(DeviceExtension->ClassDeviceObject);
28
29 /* raise irql */
30 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
31
32 /* dispatch input data */
33 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + InputDataLength + 1, &InputDataConsumed);
34
35 /* lower irql to previous level */
36 KeLowerIrql(OldIrql);
37 }
38
39 NTSTATUS
40 NTAPI
41 KbdHid_ReadCompletion(
42 IN PDEVICE_OBJECT DeviceObject,
43 IN PIRP Irp,
44 IN PVOID Context)
45 {
46 PKBDHID_DEVICE_EXTENSION DeviceExtension;
47
48 /* get device extension */
49 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
50
51 if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
52 Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
53 Irp->IoStatus.Status == STATUS_CANCELLED ||
54 DeviceExtension->StopReadReport)
55 {
56 /* failed to read or should be stopped*/
57 DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
58
59 /* report no longer active */
60 DeviceExtension->ReadReportActive = FALSE;
61
62 /* request stopping of the report cycle */
63 DeviceExtension->StopReadReport = FALSE;
64
65 /* signal completion event */
66 KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
67 return STATUS_MORE_PROCESSING_REQUIRED;
68 }
69
70 UNIMPLEMENTED
71 ASSERT(FALSE);
72
73 /* dispatch mouse action */
74 //KbdHid_DispatchInputData(DeviceExtension, &InputData);
75
76 /* re-init read */
77 KbdHid_InitiateRead(DeviceExtension);
78
79 /* stop completion */
80 return STATUS_MORE_PROCESSING_REQUIRED;
81 }
82
83 NTSTATUS
84 KbdHid_InitiateRead(
85 IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
86 {
87 PIO_STACK_LOCATION IoStack;
88 NTSTATUS Status;
89
90 /* re-use irp */
91 IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
92
93 /* init irp */
94 DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
95
96 /* get next stack location */
97 IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
98
99 /* init stack location */
100 IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
101 IoStack->Parameters.Read.Key = 0;
102 IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
103 IoStack->MajorFunction = IRP_MJ_READ;
104 IoStack->FileObject = DeviceExtension->FileObject;
105
106 /* set completion routine */
107 IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
108
109 /* read is active */
110 DeviceExtension->ReadReportActive = TRUE;
111
112 /* start the read */
113 Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
114
115 /* done */
116 return Status;
117 }
118
119 NTSTATUS
120 NTAPI
121 KbdHid_CreateCompletion(
122 IN PDEVICE_OBJECT DeviceObject,
123 IN PIRP Irp,
124 IN PVOID Context)
125 {
126 KeSetEvent((PKEVENT)Context, 0, FALSE);
127 return STATUS_MORE_PROCESSING_REQUIRED;
128 }
129
130
131 NTSTATUS
132 NTAPI
133 KbdHid_Create(
134 IN PDEVICE_OBJECT DeviceObject,
135 IN PIRP Irp)
136 {
137 PIO_STACK_LOCATION IoStack;
138 NTSTATUS Status;
139 KEVENT Event;
140 PKBDHID_DEVICE_EXTENSION DeviceExtension;
141
142 DPRINT1("[KBDHID]: IRP_MJ_CREATE\n");
143
144 /* get device extension */
145 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
146
147 /* get stack location */
148 IoStack = IoGetCurrentIrpStackLocation(Irp);
149
150 /* copy stack location to next */
151 IoCopyCurrentIrpStackLocationToNext(Irp);
152
153 /* init event */
154 KeInitializeEvent(&Event, NotificationEvent, FALSE);
155
156 /* prepare irp */
157 IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
158
159 /* call lower driver */
160 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
161 if (Status == STATUS_PENDING)
162 {
163 /* request pending */
164 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
165 }
166
167 /* check for success */
168 if (!NT_SUCCESS(Status))
169 {
170 /* failed */
171 Irp->IoStatus.Status = Status;
172 IoCompleteRequest(Irp, IO_NO_INCREMENT);
173 return Status;
174 }
175
176 /* is the driver already in use */
177 if (DeviceExtension->FileObject == NULL)
178 {
179 /* did the caller specify correct attributes */
180 ASSERT(IoStack->Parameters.Create.SecurityContext);
181 if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
182 {
183 /* store file object */
184 DeviceExtension->FileObject = IoStack->FileObject;
185
186 /* reset event */
187 KeResetEvent(&DeviceExtension->ReadCompletionEvent);
188
189 /* initiating read */
190 Status = KbdHid_InitiateRead(DeviceExtension);
191 DPRINT1("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
192 if (Status == STATUS_PENDING)
193 {
194 /* report irp is pending */
195 Status = STATUS_SUCCESS;
196 }
197 }
198 }
199
200 /* complete request */
201 Irp->IoStatus.Status = Status;
202 IoCompleteRequest(Irp, IO_NO_INCREMENT);
203 return Status;
204 }
205
206
207 NTSTATUS
208 NTAPI
209 KbdHid_Close(
210 IN PDEVICE_OBJECT DeviceObject,
211 IN PIRP Irp)
212 {
213 PKBDHID_DEVICE_EXTENSION DeviceExtension;
214
215 /* get device extension */
216 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
217
218 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
219
220 if (DeviceExtension->ReadReportActive)
221 {
222 /* request stopping of the report cycle */
223 DeviceExtension->StopReadReport = TRUE;
224
225 /* wait until the reports have been read */
226 KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
227
228 /* cancel irp */
229 IoCancelIrp(DeviceExtension->Irp);
230 }
231
232 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
233
234 /* remove file object */
235 DeviceExtension->FileObject = NULL;
236
237 /* skip location */
238 IoSkipCurrentIrpStackLocation(Irp);
239
240 /* pass irp to down the stack */
241 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
242 }
243
244 NTSTATUS
245 NTAPI
246 KbdHid_InternalDeviceControl(
247 IN PDEVICE_OBJECT DeviceObject,
248 IN PIRP Irp)
249 {
250 PIO_STACK_LOCATION IoStack;
251 PKBDHID_DEVICE_EXTENSION DeviceExtension;
252
253 /* get current stack location */
254 IoStack = IoGetCurrentIrpStackLocation(Irp);
255
256 DPRINT1("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
257
258 /* get device extension */
259 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
260
261 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
262
263 ASSERT(FALSE);
264 /* unknown request not supported */
265 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
266 IoCompleteRequest(Irp, IO_NO_INCREMENT);
267 return STATUS_NOT_SUPPORTED;
268 }
269
270 NTSTATUS
271 NTAPI
272 KbdHid_DeviceControl(
273 IN PDEVICE_OBJECT DeviceObject,
274 IN PIRP Irp)
275 {
276 PKBDHID_DEVICE_EXTENSION DeviceExtension;
277
278 /* get device extension */
279 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
280
281 /* skip stack location */
282 IoSkipCurrentIrpStackLocation(Irp);
283
284 /* pass and forget */
285 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
286 }
287
288 NTSTATUS
289 NTAPI
290 KbdHid_Power(
291 IN PDEVICE_OBJECT DeviceObject,
292 IN PIRP Irp)
293 {
294 UNIMPLEMENTED
295 return STATUS_NOT_IMPLEMENTED;
296 }
297
298 NTSTATUS
299 KbdHid_SubmitRequest(
300 PDEVICE_OBJECT DeviceObject,
301 ULONG IoControlCode,
302 ULONG InputBufferSize,
303 PVOID InputBuffer,
304 ULONG OutputBufferSize,
305 PVOID OutputBuffer)
306 {
307 KEVENT Event;
308 PKBDHID_DEVICE_EXTENSION DeviceExtension;
309 PIRP Irp;
310 NTSTATUS Status;
311 IO_STATUS_BLOCK IoStatus;
312
313 /* get device extension */
314 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
315
316 /* init event */
317 KeInitializeEvent(&Event, NotificationEvent, FALSE);
318
319 /* build request */
320 Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
321 if (!Irp)
322 {
323 /* no memory */
324 return STATUS_INSUFFICIENT_RESOURCES;
325 }
326
327 /* send request */
328 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
329 if (Status == STATUS_PENDING)
330 {
331 /* wait for request to complete */
332 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
333 Status = IoStatus.Status;
334 }
335
336 /* done */
337 return Status;
338 }
339
340 NTSTATUS
341 NTAPI
342 KbdHid_StartDevice(
343 IN PDEVICE_OBJECT DeviceObject)
344 {
345 NTSTATUS Status;
346 ULONG Buttons;
347 HID_COLLECTION_INFORMATION Information;
348 PHIDP_PREPARSED_DATA PreparsedData;
349 HIDP_CAPS Capabilities;
350 PKBDHID_DEVICE_EXTENSION DeviceExtension;
351 PUSAGE_AND_PAGE Buffer;
352
353 /* get device extension */
354 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
355
356 /* query collection information */
357 Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
358 if (!NT_SUCCESS(Status))
359 {
360 /* failed to query collection information */
361 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
362 return Status;
363 }
364
365 /* lets allocate space for preparsed data */
366 PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
367 if (!PreparsedData)
368 {
369 /* no memory */
370 DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
371 return STATUS_INSUFFICIENT_RESOURCES;
372 }
373
374 /* now obtain the preparsed data */
375 Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
376 if (!NT_SUCCESS(Status))
377 {
378 /* failed to get preparsed data */
379 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
380 ExFreePool(PreparsedData);
381 return Status;
382 }
383
384 /* lets get the caps */
385 Status = HidP_GetCaps(PreparsedData, &Capabilities);
386 if (Status != HIDP_STATUS_SUCCESS)
387 {
388 /* failed to get capabilities */
389 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
390 ExFreePool(PreparsedData);
391 return Status;
392 }
393
394 DPRINT1("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
395
396 /* init input report*/
397 DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
398 ASSERT(DeviceExtension->ReportLength);
399 DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
400 ASSERT(DeviceExtension->Report);
401 RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
402
403 /* build mdl */
404 DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
405 ASSERT(DeviceExtension->ReportMDL);
406
407 /* init mdl */
408 MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
409
410 /* get max number of buttons */
411 Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
412 DPRINT1("[KBDHID] Buttons %lu\n", Buttons);
413 ASSERT(Buttons > 0);
414
415 /* now allocate an array for those buttons */
416 Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
417 if (!Buffer)
418 {
419 /* no memory */
420 ExFreePool(PreparsedData);
421 return STATUS_INSUFFICIENT_RESOURCES;
422 }
423
424 /* init usage lists */
425 RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
426 DeviceExtension->CurrentUsageList = Buffer;
427 Buffer += Buttons;
428 DeviceExtension->PreviousUsageList = Buffer;
429 Buffer += Buttons;
430 DeviceExtension->MakeUsageList = Buffer;
431 Buffer += Buttons;
432 DeviceExtension->BreakUsageList = Buffer;
433
434 //
435 // FIMXE: implement device hacks
436 //
437 // UsageMappings
438 // KeyboardTypeOverride
439 // KeyboardSubTypeOverride
440 // KeyboardNumberTotalKeysOverride
441 // KeyboardNumberFunctionKeysOverride
442 // KeyboardNumberIndicatorsOverride
443
444 /* store number of buttons */
445 DeviceExtension->UsageListLength = (USHORT)Buttons;
446
447 /* store preparsed data */
448 DeviceExtension->PreparsedData = PreparsedData;
449
450 /* completed successfully */
451 return STATUS_SUCCESS;
452 }
453
454 NTSTATUS
455 NTAPI
456 KbdHid_StartDeviceCompletion(
457 IN PDEVICE_OBJECT DeviceObject,
458 IN PIRP Irp,
459 IN PVOID Context)
460 {
461 KeSetEvent((PKEVENT)Context, 0, FALSE);
462 return STATUS_MORE_PROCESSING_REQUIRED;
463 }
464
465 NTSTATUS
466 NTAPI
467 KbdHid_Flush(
468 IN PDEVICE_OBJECT DeviceObject,
469 IN PIRP Irp)
470 {
471 PIO_STACK_LOCATION IoStack;
472 PKBDHID_DEVICE_EXTENSION DeviceExtension;
473
474 /* get device extension */
475 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
476
477 /* skip current stack location */
478 IoSkipCurrentIrpStackLocation(Irp);
479
480 /* get next stack location */
481 IoStack = IoGetNextIrpStackLocation(Irp);
482
483 /* change request to hid flush queue request */
484 IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
485 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
486
487 /* call device */
488 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
489 }
490
491 NTSTATUS
492 NTAPI
493 KbdHid_Pnp(
494 IN PDEVICE_OBJECT DeviceObject,
495 IN PIRP Irp)
496 {
497 PIO_STACK_LOCATION IoStack;
498 KEVENT Event;
499 NTSTATUS Status;
500 PKBDHID_DEVICE_EXTENSION DeviceExtension;
501
502 /* get device extension */
503 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
504
505 /* get current irp stack */
506 IoStack = IoGetCurrentIrpStackLocation(Irp);
507 DPRINT1("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
508
509 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)
510 {
511 /* indicate success */
512 Irp->IoStatus.Status = STATUS_SUCCESS;
513
514 /* skip irp stack location */
515 IoSkipCurrentIrpStackLocation(Irp);
516
517 /* dispatch to lower device */
518 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
519 }
520 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
521 {
522 /* FIXME synchronization */
523
524 /* cancel irp */
525 IoCancelIrp(DeviceExtension->Irp);
526
527 /* indicate success */
528 Irp->IoStatus.Status = STATUS_SUCCESS;
529
530 /* skip irp stack location */
531 IoSkipCurrentIrpStackLocation(Irp);
532
533 /* dispatch to lower device */
534 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
535
536 IoFreeIrp(DeviceExtension->Irp);
537 IoDetachDevice(DeviceExtension->NextDeviceObject);
538 IoDeleteDevice(DeviceObject);
539 return Status;
540 }
541 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
542 {
543 /* init event */
544 KeInitializeEvent(&Event, NotificationEvent, FALSE);
545
546 /* copy stack location */
547 IoCopyCurrentIrpStackLocationToNext (Irp);
548
549 /* set completion routine */
550 IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
551 Irp->IoStatus.Status = 0;
552
553 /* pass request */
554 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
555 if (Status == STATUS_PENDING)
556 {
557 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
558 Status = Irp->IoStatus.Status;
559 }
560
561 if (!NT_SUCCESS(Status))
562 {
563 /* failed */
564 Irp->IoStatus.Status = Status;
565 IoCompleteRequest(Irp, IO_NO_INCREMENT);
566 return Status;
567 }
568
569 /* lets start the device */
570 Status = KbdHid_StartDevice(DeviceObject);
571 DPRINT1("KbdHid_StartDevice %x\n", Status);
572
573 /* complete request */
574 Irp->IoStatus.Status = Status;
575 IoCompleteRequest(Irp, IO_NO_INCREMENT);
576
577 /* done */
578 return Status;
579 }
580 else
581 {
582 /* skip irp stack location */
583 IoSkipCurrentIrpStackLocation(Irp);
584
585 /* dispatch to lower device */
586 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
587 }
588 }
589
590 NTSTATUS
591 NTAPI
592 KbdHid_AddDevice(
593 IN PDRIVER_OBJECT DriverObject,
594 IN PDEVICE_OBJECT PhysicalDeviceObject)
595 {
596 NTSTATUS Status;
597 PDEVICE_OBJECT DeviceObject, NextDeviceObject;
598 PKBDHID_DEVICE_EXTENSION DeviceExtension;
599 POWER_STATE State;
600
601 /* create device object */
602 Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
603 if (!NT_SUCCESS(Status))
604 {
605 /* failed to create device object */
606 return Status;
607 }
608
609 /* now attach it */
610 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
611 if (!NextDeviceObject)
612 {
613 /* failed to attach */
614 IoDeleteDevice(DeviceObject);
615 return STATUS_DEVICE_NOT_CONNECTED;
616 }
617
618 /* get device extension */
619 DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
620
621 /* zero extension */
622 RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
623
624 /* init device extension */
625 DeviceExtension->NextDeviceObject = NextDeviceObject;
626 KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
627 DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
628
629 /* FIXME handle allocation error */
630 ASSERT(DeviceExtension->Irp);
631
632 /* set power state to D0 */
633 State.DeviceState = PowerDeviceD0;
634 PoSetPowerState(DeviceObject, DevicePowerState, State);
635
636 /* init device object */
637 DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
638 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
639
640 /* completed successfully */
641 return STATUS_SUCCESS;
642 }
643
644 VOID
645 NTAPI
646 KbdHid_Unload(
647 IN PDRIVER_OBJECT DriverObject)
648 {
649 UNIMPLEMENTED
650 }
651
652
653 NTSTATUS
654 NTAPI
655 DriverEntry(
656 IN PDRIVER_OBJECT DriverObject,
657 IN PUNICODE_STRING RegPath)
658 {
659 /* initialize driver object */
660 DriverObject->DriverUnload = KbdHid_Unload;
661 DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
662 DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create;
663 DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close;
664 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush;
665 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl;
666 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl;
667 DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power;
668 DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp;
669 DriverObject->DriverUnload = KbdHid_Unload;
670 DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
671
672 /* done */
673 return STATUS_SUCCESS;
674 }