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 = 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(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 = 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, 140 HIDP_LINK_COLLECTION_UNSPECIFIED, 141 DeviceExtension->CurrentUsageList, 142 &ButtonLength, 143 DeviceExtension->PreparsedData, 144 DeviceExtension->Report, 145 DeviceExtension->ReportLength); 146 ASSERT(Status == HIDP_STATUS_SUCCESS); 147 148 /* FIXME check if needs mapping */ 149 150 /* get usage difference */ 151 Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, 152 DeviceExtension->CurrentUsageList, 153 DeviceExtension->BreakUsageList, 154 DeviceExtension->MakeUsageList, 155 DeviceExtension->UsageListLength); 156 ASSERT(Status == HIDP_STATUS_SUCCESS); 157 158 /* replace previous usage list with current list */ 159 RtlMoveMemory(DeviceExtension->PreviousUsageList, 160 DeviceExtension->CurrentUsageList, 161 sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength); 162 163 /* translate break usage list */ 164 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->BreakUsageList, 165 DeviceExtension->UsageListLength, 166 HidP_Keyboard_Break, 167 &DeviceExtension->ModifierState, 168 KbdHid_InsertScanCodes, 169 DeviceExtension); 170 ASSERT(Status == HIDP_STATUS_SUCCESS); 171 172 /* translate new usage list */ 173 HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->MakeUsageList, 174 DeviceExtension->UsageListLength, 175 HidP_Keyboard_Make, 176 &DeviceExtension->ModifierState, 177 KbdHid_InsertScanCodes, 178 DeviceExtension); 179 ASSERT(Status == HIDP_STATUS_SUCCESS); 180 181 /* re-init read */ 182 KbdHid_InitiateRead(DeviceExtension); 183 184 /* stop completion */ 185 return STATUS_MORE_PROCESSING_REQUIRED; 186 } 187 188 NTSTATUS 189 KbdHid_InitiateRead( 190 IN PKBDHID_DEVICE_EXTENSION DeviceExtension) 191 { 192 PIO_STACK_LOCATION IoStack; 193 NTSTATUS Status; 194 195 /* re-use irp */ 196 IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS); 197 198 /* init irp */ 199 DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL; 200 201 /* get next stack location */ 202 IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp); 203 204 /* init stack location */ 205 IoStack->Parameters.Read.Length = DeviceExtension->ReportLength; 206 IoStack->Parameters.Read.Key = 0; 207 IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL; 208 IoStack->MajorFunction = IRP_MJ_READ; 209 IoStack->FileObject = DeviceExtension->FileObject; 210 211 /* set completion routine */ 212 IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE); 213 214 /* read is active */ 215 DeviceExtension->ReadReportActive = TRUE; 216 217 /* start the read */ 218 Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp); 219 220 /* done */ 221 return Status; 222 } 223 224 NTSTATUS 225 NTAPI 226 KbdHid_CreateCompletion( 227 IN PDEVICE_OBJECT DeviceObject, 228 IN PIRP Irp, 229 IN PVOID Context) 230 { 231 KeSetEvent((PKEVENT)Context, 0, FALSE); 232 return STATUS_MORE_PROCESSING_REQUIRED; 233 } 234 235 236 NTSTATUS 237 NTAPI 238 KbdHid_Create( 239 IN PDEVICE_OBJECT DeviceObject, 240 IN PIRP Irp) 241 { 242 PIO_STACK_LOCATION IoStack; 243 NTSTATUS Status; 244 KEVENT Event; 245 PKBDHID_DEVICE_EXTENSION DeviceExtension; 246 247 DPRINT("[KBDHID]: IRP_MJ_CREATE\n"); 248 249 /* get device extension */ 250 DeviceExtension = DeviceObject->DeviceExtension; 251 252 /* get stack location */ 253 IoStack = IoGetCurrentIrpStackLocation(Irp); 254 255 /* copy stack location to next */ 256 IoCopyCurrentIrpStackLocationToNext(Irp); 257 258 /* init event */ 259 KeInitializeEvent(&Event, NotificationEvent, FALSE); 260 261 /* prepare irp */ 262 IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE); 263 264 /* call lower driver */ 265 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 266 if (Status == STATUS_PENDING) 267 { 268 /* request pending */ 269 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 270 } 271 272 /* check for success */ 273 if (!NT_SUCCESS(Status)) 274 { 275 /* failed */ 276 Irp->IoStatus.Status = Status; 277 IoCompleteRequest(Irp, IO_NO_INCREMENT); 278 return Status; 279 } 280 281 /* is the driver already in use */ 282 if (DeviceExtension->FileObject == NULL) 283 { 284 /* did the caller specify correct attributes */ 285 ASSERT(IoStack->Parameters.Create.SecurityContext); 286 if (IoStack->Parameters.Create.SecurityContext->DesiredAccess) 287 { 288 /* store file object */ 289 DeviceExtension->FileObject = IoStack->FileObject; 290 291 /* reset event */ 292 KeClearEvent(&DeviceExtension->ReadCompletionEvent); 293 294 /* initiating read */ 295 Status = KbdHid_InitiateRead(DeviceExtension); 296 DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status); 297 if (Status == STATUS_PENDING) 298 { 299 /* report irp is pending */ 300 Status = STATUS_SUCCESS; 301 } 302 } 303 } 304 305 /* complete request */ 306 Irp->IoStatus.Status = Status; 307 IoCompleteRequest(Irp, IO_NO_INCREMENT); 308 return Status; 309 } 310 311 312 NTSTATUS 313 NTAPI 314 KbdHid_Close( 315 IN PDEVICE_OBJECT DeviceObject, 316 IN PIRP Irp) 317 { 318 PKBDHID_DEVICE_EXTENSION DeviceExtension; 319 320 /* get device extension */ 321 DeviceExtension = DeviceObject->DeviceExtension; 322 323 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive); 324 325 if (DeviceExtension->ReadReportActive) 326 { 327 /* request stopping of the report cycle */ 328 DeviceExtension->StopReadReport = TRUE; 329 330 /* wait until the reports have been read */ 331 KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL); 332 333 /* cancel irp */ 334 IoCancelIrp(DeviceExtension->Irp); 335 } 336 337 DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive); 338 339 /* remove file object */ 340 DeviceExtension->FileObject = NULL; 341 342 /* skip location */ 343 IoSkipCurrentIrpStackLocation(Irp); 344 345 /* pass irp to down the stack */ 346 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 347 } 348 349 NTSTATUS 350 NTAPI 351 KbdHid_InternalDeviceControl( 352 IN PDEVICE_OBJECT DeviceObject, 353 IN PIRP Irp) 354 { 355 PIO_STACK_LOCATION IoStack; 356 PKBDHID_DEVICE_EXTENSION DeviceExtension; 357 PCONNECT_DATA Data; 358 PKEYBOARD_ATTRIBUTES Attributes; 359 360 /* get current stack location */ 361 IoStack = IoGetCurrentIrpStackLocation(Irp); 362 363 DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); 364 365 /* get device extension */ 366 DeviceExtension = DeviceObject->DeviceExtension; 367 368 switch (IoStack->Parameters.DeviceIoControl.IoControlCode) 369 { 370 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: 371 /* verify output buffer length */ 372 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES)) 373 { 374 /* invalid request */ 375 DPRINT1("[KBDHID] IOCTL_KEYBOARD_QUERY_ATTRIBUTES Buffer too small\n"); 376 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 377 IoCompleteRequest(Irp, IO_NO_INCREMENT); 378 return STATUS_BUFFER_TOO_SMALL; 379 } 380 381 /* get output buffer */ 382 Attributes = Irp->AssociatedIrp.SystemBuffer; 383 384 /* copy attributes */ 385 RtlCopyMemory(Attributes, 386 &DeviceExtension->Attributes, 387 sizeof(KEYBOARD_ATTRIBUTES)); 388 389 /* complete request */ 390 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES); 391 Irp->IoStatus.Status = STATUS_SUCCESS; 392 IoCompleteRequest(Irp, IO_NO_INCREMENT); 393 return STATUS_SUCCESS; 394 395 case IOCTL_INTERNAL_KEYBOARD_CONNECT: 396 /* verify input buffer length */ 397 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) 398 { 399 /* invalid request */ 400 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 401 IoCompleteRequest(Irp, IO_NO_INCREMENT); 402 return STATUS_INVALID_PARAMETER; 403 } 404 405 /* is it already connected */ 406 if (DeviceExtension->ClassService) 407 { 408 /* already connected */ 409 Irp->IoStatus.Status = STATUS_SHARING_VIOLATION; 410 IoCompleteRequest(Irp, IO_NO_INCREMENT); 411 return STATUS_SHARING_VIOLATION; 412 } 413 414 /* get connect data */ 415 Data = IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 416 417 /* store connect details */ 418 DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject; 419 DeviceExtension->ClassService = Data->ClassService; 420 421 /* completed successfully */ 422 Irp->IoStatus.Status = STATUS_SUCCESS; 423 IoCompleteRequest(Irp, IO_NO_INCREMENT); 424 return STATUS_SUCCESS; 425 426 case IOCTL_INTERNAL_KEYBOARD_DISCONNECT: 427 /* not implemented */ 428 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 429 IoCompleteRequest(Irp, IO_NO_INCREMENT); 430 return STATUS_NOT_IMPLEMENTED; 431 432 case IOCTL_INTERNAL_KEYBOARD_ENABLE: 433 /* not supported */ 434 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 435 IoCompleteRequest(Irp, IO_NO_INCREMENT); 436 return STATUS_NOT_SUPPORTED; 437 438 case IOCTL_INTERNAL_KEYBOARD_DISABLE: 439 /* not supported */ 440 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 441 IoCompleteRequest(Irp, IO_NO_INCREMENT); 442 return STATUS_NOT_SUPPORTED; 443 444 case IOCTL_KEYBOARD_QUERY_INDICATORS: 445 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) 446 { 447 /* invalid parameter */ 448 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 449 IoCompleteRequest(Irp, IO_NO_INCREMENT); 450 return STATUS_INVALID_PARAMETER; 451 } 452 453 /* copy indicators */ 454 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 455 &DeviceExtension->KeyboardIndicator, 456 sizeof(KEYBOARD_INDICATOR_PARAMETERS)); 457 458 /* complete request */ 459 Irp->IoStatus.Status = STATUS_SUCCESS; 460 Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS); 461 IoCompleteRequest(Irp, IO_NO_INCREMENT); 462 return STATUS_NOT_IMPLEMENTED; 463 464 case IOCTL_KEYBOARD_QUERY_TYPEMATIC: 465 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) 466 { 467 /* invalid parameter */ 468 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 469 IoCompleteRequest(Irp, IO_NO_INCREMENT); 470 return STATUS_INVALID_PARAMETER; 471 } 472 473 /* copy indicators */ 474 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 475 &DeviceExtension->KeyboardTypematic, 476 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)); 477 478 /* done */ 479 Irp->IoStatus.Status = STATUS_SUCCESS; 480 Irp->IoStatus.Information = sizeof(KEYBOARD_TYPEMATIC_PARAMETERS); 481 IoCompleteRequest(Irp, IO_NO_INCREMENT); 482 return STATUS_SUCCESS; 483 484 case IOCTL_KEYBOARD_SET_INDICATORS: 485 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) 486 { 487 /* invalid parameter */ 488 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 489 IoCompleteRequest(Irp, IO_NO_INCREMENT); 490 return STATUS_INVALID_PARAMETER; 491 } 492 493 /* copy indicators */ 494 RtlCopyMemory(&DeviceExtension->KeyboardIndicator, 495 Irp->AssociatedIrp.SystemBuffer, 496 sizeof(KEYBOARD_INDICATOR_PARAMETERS)); 497 498 /* done */ 499 Irp->IoStatus.Status = STATUS_SUCCESS; 500 Irp->IoStatus.Information = 0; 501 IoCompleteRequest(Irp, IO_NO_INCREMENT); 502 return STATUS_SUCCESS; 503 504 case IOCTL_KEYBOARD_SET_TYPEMATIC: 505 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) 506 { 507 /* invalid parameter */ 508 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 509 IoCompleteRequest(Irp, IO_NO_INCREMENT); 510 return STATUS_INVALID_PARAMETER; 511 } 512 513 /* copy indicators */ 514 RtlCopyMemory(&DeviceExtension->KeyboardTypematic, 515 Irp->AssociatedIrp.SystemBuffer, 516 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)); 517 518 /* done */ 519 Irp->IoStatus.Status = STATUS_SUCCESS; 520 Irp->IoStatus.Information = 0; 521 IoCompleteRequest(Irp, IO_NO_INCREMENT); 522 return STATUS_SUCCESS; 523 524 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: 525 /* not implemented */ 526 DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n"); 527 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 528 IoCompleteRequest(Irp, IO_NO_INCREMENT); 529 return STATUS_NOT_IMPLEMENTED; 530 } 531 532 /* unknown control code */ 533 DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); 534 /* unknown request not supported */ 535 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 536 IoCompleteRequest(Irp, IO_NO_INCREMENT); 537 return STATUS_NOT_SUPPORTED; 538 } 539 540 NTSTATUS 541 NTAPI 542 KbdHid_DeviceControl( 543 IN PDEVICE_OBJECT DeviceObject, 544 IN PIRP Irp) 545 { 546 PKBDHID_DEVICE_EXTENSION DeviceExtension; 547 548 /* get device extension */ 549 DeviceExtension = DeviceObject->DeviceExtension; 550 551 /* skip stack location */ 552 IoSkipCurrentIrpStackLocation(Irp); 553 554 /* pass and forget */ 555 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 556 } 557 558 NTSTATUS 559 NTAPI 560 KbdHid_Power( 561 IN PDEVICE_OBJECT DeviceObject, 562 IN PIRP Irp) 563 { 564 PKBDHID_DEVICE_EXTENSION DeviceExtension; 565 566 DeviceExtension = DeviceObject->DeviceExtension; 567 PoStartNextPowerIrp(Irp); 568 IoSkipCurrentIrpStackLocation(Irp); 569 return PoCallDriver(DeviceExtension->NextDeviceObject, Irp); 570 } 571 572 NTSTATUS 573 NTAPI 574 KbdHid_SystemControl( 575 IN PDEVICE_OBJECT DeviceObject, 576 IN PIRP Irp) 577 { 578 PKBDHID_DEVICE_EXTENSION DeviceExtension; 579 580 DeviceExtension = DeviceObject->DeviceExtension; 581 IoSkipCurrentIrpStackLocation(Irp); 582 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 583 } 584 585 NTSTATUS 586 KbdHid_SubmitRequest( 587 PDEVICE_OBJECT DeviceObject, 588 ULONG IoControlCode, 589 ULONG InputBufferSize, 590 PVOID InputBuffer, 591 ULONG OutputBufferSize, 592 PVOID OutputBuffer) 593 { 594 KEVENT Event; 595 PKBDHID_DEVICE_EXTENSION DeviceExtension; 596 PIRP Irp; 597 NTSTATUS Status; 598 IO_STATUS_BLOCK IoStatus; 599 600 /* get device extension */ 601 DeviceExtension = DeviceObject->DeviceExtension; 602 603 /* init event */ 604 KeInitializeEvent(&Event, NotificationEvent, FALSE); 605 606 /* build request */ 607 Irp = IoBuildDeviceIoControlRequest(IoControlCode, 608 DeviceExtension->NextDeviceObject, 609 InputBuffer, 610 InputBufferSize, 611 OutputBuffer, 612 OutputBufferSize, 613 FALSE, 614 &Event, 615 &IoStatus); 616 if (!Irp) 617 { 618 /* no memory */ 619 return STATUS_INSUFFICIENT_RESOURCES; 620 } 621 622 /* send request */ 623 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 624 if (Status == STATUS_PENDING) 625 { 626 /* wait for request to complete */ 627 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 628 Status = IoStatus.Status; 629 } 630 631 /* done */ 632 return Status; 633 } 634 635 NTSTATUS 636 NTAPI 637 KbdHid_StartDevice( 638 IN PDEVICE_OBJECT DeviceObject) 639 { 640 NTSTATUS Status; 641 ULONG Buttons; 642 HID_COLLECTION_INFORMATION Information; 643 PHIDP_PREPARSED_DATA PreparsedData; 644 HIDP_CAPS Capabilities; 645 PKBDHID_DEVICE_EXTENSION DeviceExtension; 646 PUSAGE_AND_PAGE Buffer; 647 648 /* get device extension */ 649 DeviceExtension = DeviceObject->DeviceExtension; 650 651 /* query collection information */ 652 Status = KbdHid_SubmitRequest(DeviceObject, 653 IOCTL_HID_GET_COLLECTION_INFORMATION, 654 0, 655 NULL, 656 sizeof(HID_COLLECTION_INFORMATION), 657 &Information); 658 if (!NT_SUCCESS(Status)) 659 { 660 /* failed to query collection information */ 661 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status); 662 return Status; 663 } 664 665 /* lets allocate space for preparsed data */ 666 PreparsedData = ExAllocatePoolWithTag(NonPagedPool, Information.DescriptorSize, KBDHID_TAG); 667 if (!PreparsedData) 668 { 669 /* no memory */ 670 DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize); 671 return STATUS_INSUFFICIENT_RESOURCES; 672 } 673 674 /* now obtain the preparsed data */ 675 Status = KbdHid_SubmitRequest(DeviceObject, 676 IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 677 0, 678 NULL, 679 Information.DescriptorSize, 680 PreparsedData); 681 if (!NT_SUCCESS(Status)) 682 { 683 /* failed to get preparsed data */ 684 DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status); 685 ExFreePoolWithTag(PreparsedData, KBDHID_TAG); 686 return Status; 687 } 688 689 /* lets get the caps */ 690 Status = HidP_GetCaps(PreparsedData, &Capabilities); 691 if (Status != HIDP_STATUS_SUCCESS) 692 { 693 /* failed to get capabilities */ 694 DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status); 695 ExFreePoolWithTag(PreparsedData, KBDHID_TAG); 696 return Status; 697 } 698 699 DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength); 700 701 /* init input report */ 702 DeviceExtension->ReportLength = Capabilities.InputReportByteLength; 703 ASSERT(DeviceExtension->ReportLength); 704 DeviceExtension->Report = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->ReportLength, KBDHID_TAG); 705 ASSERT(DeviceExtension->Report); 706 RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength); 707 708 /* build mdl */ 709 DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, 710 DeviceExtension->ReportLength, 711 FALSE, 712 FALSE, 713 NULL); 714 ASSERT(DeviceExtension->ReportMDL); 715 716 /* init mdl */ 717 MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL); 718 719 /* get max number of buttons */ 720 Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_KEYBOARD, PreparsedData); 721 DPRINT("[KBDHID] Buttons %lu\n", Buttons); 722 ASSERT(Buttons > 0); 723 724 /* now allocate an array for those buttons */ 725 Buffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons, KBDHID_TAG); 726 if (!Buffer) 727 { 728 /* no memory */ 729 ExFreePoolWithTag(PreparsedData, KBDHID_TAG); 730 return STATUS_INSUFFICIENT_RESOURCES; 731 } 732 DeviceExtension->UsageListBuffer = Buffer; 733 734 /* init usage lists */ 735 RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons); 736 DeviceExtension->CurrentUsageList = Buffer; 737 Buffer += Buttons; 738 DeviceExtension->PreviousUsageList = Buffer; 739 Buffer += Buttons; 740 DeviceExtension->MakeUsageList = Buffer; 741 Buffer += Buttons; 742 DeviceExtension->BreakUsageList = Buffer; 743 744 // 745 // FIMXE: implement device hacks 746 // 747 // UsageMappings 748 // KeyboardTypeOverride 749 // KeyboardSubTypeOverride 750 // KeyboardNumberTotalKeysOverride 751 // KeyboardNumberFunctionKeysOverride 752 // KeyboardNumberIndicatorsOverride 753 754 /* store number of buttons */ 755 DeviceExtension->UsageListLength = (USHORT)Buttons; 756 757 /* store preparsed data */ 758 DeviceExtension->PreparsedData = PreparsedData; 759 760 /* completed successfully */ 761 return STATUS_SUCCESS; 762 } 763 764 NTSTATUS 765 NTAPI 766 KbdHid_StartDeviceCompletion( 767 IN PDEVICE_OBJECT DeviceObject, 768 IN PIRP Irp, 769 IN PVOID Context) 770 { 771 KeSetEvent((PKEVENT)Context, 0, FALSE); 772 return STATUS_MORE_PROCESSING_REQUIRED; 773 } 774 775 NTSTATUS 776 NTAPI 777 KbdHid_FreeResources( 778 IN PDEVICE_OBJECT DeviceObject) 779 { 780 PKBDHID_DEVICE_EXTENSION DeviceExtension; 781 782 /* get device extension */ 783 DeviceExtension = DeviceObject->DeviceExtension; 784 785 /* free resources */ 786 if (DeviceExtension->PreparsedData) 787 { 788 ExFreePoolWithTag(DeviceExtension->PreparsedData, KBDHID_TAG); 789 DeviceExtension->PreparsedData = NULL; 790 } 791 792 if (DeviceExtension->UsageListBuffer) 793 { 794 ExFreePoolWithTag(DeviceExtension->UsageListBuffer, KBDHID_TAG); 795 DeviceExtension->UsageListBuffer = NULL; 796 DeviceExtension->CurrentUsageList = NULL; 797 DeviceExtension->PreviousUsageList = NULL; 798 DeviceExtension->MakeUsageList = NULL; 799 DeviceExtension->BreakUsageList = NULL; 800 } 801 802 if (DeviceExtension->ReportMDL) 803 { 804 IoFreeMdl(DeviceExtension->ReportMDL); 805 DeviceExtension->ReportMDL = NULL; 806 } 807 808 if (DeviceExtension->Report) 809 { 810 ExFreePoolWithTag(DeviceExtension->Report, KBDHID_TAG); 811 DeviceExtension->Report = NULL; 812 } 813 814 return STATUS_SUCCESS; 815 } 816 817 NTSTATUS 818 NTAPI 819 KbdHid_Flush( 820 IN PDEVICE_OBJECT DeviceObject, 821 IN PIRP Irp) 822 { 823 PIO_STACK_LOCATION IoStack; 824 PKBDHID_DEVICE_EXTENSION DeviceExtension; 825 826 /* get device extension */ 827 DeviceExtension = DeviceObject->DeviceExtension; 828 829 /* skip current stack location */ 830 IoSkipCurrentIrpStackLocation(Irp); 831 832 /* get next stack location */ 833 IoStack = IoGetNextIrpStackLocation(Irp); 834 835 /* change request to hid flush queue request */ 836 IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; 837 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE; 838 839 /* call device */ 840 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 841 } 842 843 NTSTATUS 844 NTAPI 845 KbdHid_Pnp( 846 IN PDEVICE_OBJECT DeviceObject, 847 IN PIRP Irp) 848 { 849 PIO_STACK_LOCATION IoStack; 850 KEVENT Event; 851 NTSTATUS Status; 852 PKBDHID_DEVICE_EXTENSION DeviceExtension; 853 854 /* get device extension */ 855 DeviceExtension = DeviceObject->DeviceExtension; 856 857 /* get current irp stack */ 858 IoStack = IoGetCurrentIrpStackLocation(Irp); 859 DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction); 860 861 switch (IoStack->MinorFunction) 862 { 863 case IRP_MN_STOP_DEVICE: 864 case IRP_MN_SURPRISE_REMOVAL: 865 /* free resources */ 866 KbdHid_FreeResources(DeviceObject); 867 /* fall through */ 868 case IRP_MN_CANCEL_REMOVE_DEVICE: 869 case IRP_MN_QUERY_STOP_DEVICE: 870 case IRP_MN_CANCEL_STOP_DEVICE: 871 case IRP_MN_QUERY_REMOVE_DEVICE: 872 /* indicate success */ 873 Irp->IoStatus.Status = STATUS_SUCCESS; 874 875 /* skip irp stack location */ 876 IoSkipCurrentIrpStackLocation(Irp); 877 878 /* dispatch to lower device */ 879 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 880 881 case IRP_MN_REMOVE_DEVICE: 882 /* FIXME synchronization */ 883 884 /* cancel irp */ 885 IoCancelIrp(DeviceExtension->Irp); 886 887 /* free resources */ 888 KbdHid_FreeResources(DeviceObject); 889 890 /* indicate success */ 891 Irp->IoStatus.Status = STATUS_SUCCESS; 892 893 /* skip irp stack location */ 894 IoSkipCurrentIrpStackLocation(Irp); 895 896 /* dispatch to lower device */ 897 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 898 899 IoFreeIrp(DeviceExtension->Irp); 900 IoDetachDevice(DeviceExtension->NextDeviceObject); 901 IoDeleteDevice(DeviceObject); 902 return Status; 903 904 case IRP_MN_START_DEVICE: 905 /* init event */ 906 KeInitializeEvent(&Event, NotificationEvent, FALSE); 907 908 /* copy stack location */ 909 IoCopyCurrentIrpStackLocationToNext (Irp); 910 911 /* set completion routine */ 912 IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE); 913 Irp->IoStatus.Status = 0; 914 915 /* pass request */ 916 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 917 if (Status == STATUS_PENDING) 918 { 919 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 920 Status = Irp->IoStatus.Status; 921 } 922 923 if (!NT_SUCCESS(Status)) 924 { 925 /* failed */ 926 Irp->IoStatus.Status = Status; 927 IoCompleteRequest(Irp, IO_NO_INCREMENT); 928 return Status; 929 } 930 931 /* lets start the device */ 932 Status = KbdHid_StartDevice(DeviceObject); 933 DPRINT("KbdHid_StartDevice %x\n", Status); 934 935 /* complete request */ 936 Irp->IoStatus.Status = Status; 937 IoCompleteRequest(Irp, IO_NO_INCREMENT); 938 939 /* done */ 940 return Status; 941 942 default: 943 /* skip irp stack location */ 944 IoSkipCurrentIrpStackLocation(Irp); 945 946 /* dispatch to lower device */ 947 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 948 } 949 } 950 951 NTSTATUS 952 NTAPI 953 KbdHid_AddDevice( 954 IN PDRIVER_OBJECT DriverObject, 955 IN PDEVICE_OBJECT PhysicalDeviceObject) 956 { 957 NTSTATUS Status; 958 PDEVICE_OBJECT DeviceObject, NextDeviceObject; 959 PKBDHID_DEVICE_EXTENSION DeviceExtension; 960 POWER_STATE State; 961 962 /* create device object */ 963 Status = IoCreateDevice(DriverObject, 964 sizeof(KBDHID_DEVICE_EXTENSION), 965 NULL, 966 FILE_DEVICE_KEYBOARD, 967 0, 968 FALSE, 969 &DeviceObject); 970 if (!NT_SUCCESS(Status)) 971 { 972 /* failed to create device object */ 973 return Status; 974 } 975 976 /* now attach it */ 977 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); 978 if (!NextDeviceObject) 979 { 980 /* failed to attach */ 981 IoDeleteDevice(DeviceObject); 982 return STATUS_DEVICE_NOT_CONNECTED; 983 } 984 985 /* get device extension */ 986 DeviceExtension = DeviceObject->DeviceExtension; 987 988 /* zero extension */ 989 RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION)); 990 991 /* init device extension */ 992 DeviceExtension->NextDeviceObject = NextDeviceObject; 993 KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE); 994 995 /* init keyboard attributes */ 996 DeviceExtension->Attributes.KeyboardIdentifier.Type = KEYBOARD_TYPE_UNKNOWN; 997 DeviceExtension->Attributes.KeyboardIdentifier.Subtype = MICROSOFT_KBD_101_TYPE; 998 DeviceExtension->Attributes.NumberOfFunctionKeys = MICROSOFT_KBD_FUNC; 999 DeviceExtension->Attributes.NumberOfIndicators = 3; // caps, num lock, scroll lock 1000 DeviceExtension->Attributes.NumberOfKeysTotal = 101; 1001 DeviceExtension->Attributes.InputDataQueueLength = 1; 1002 DeviceExtension->Attributes.KeyRepeatMinimum.Rate = KEYBOARD_TYPEMATIC_RATE_MINIMUM; 1003 DeviceExtension->Attributes.KeyRepeatMinimum.Delay = KEYBOARD_TYPEMATIC_DELAY_MINIMUM; 1004 DeviceExtension->Attributes.KeyRepeatMaximum.Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT; 1005 DeviceExtension->Attributes.KeyRepeatMaximum.Delay = KEYBOARD_TYPEMATIC_DELAY_MAXIMUM; 1006 1007 /* allocate irp */ 1008 DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE); 1009 1010 /* FIXME handle allocation error */ 1011 ASSERT(DeviceExtension->Irp); 1012 1013 /* set power state to D0 */ 1014 State.DeviceState = PowerDeviceD0; 1015 PoSetPowerState(DeviceObject, DevicePowerState, State); 1016 1017 /* init device object */ 1018 DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; 1019 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1020 1021 /* completed successfully */ 1022 return STATUS_SUCCESS; 1023 } 1024 1025 VOID 1026 NTAPI 1027 KbdHid_Unload( 1028 IN PDRIVER_OBJECT DriverObject) 1029 { 1030 UNIMPLEMENTED; 1031 } 1032 1033 1034 NTSTATUS 1035 NTAPI 1036 DriverEntry( 1037 IN PDRIVER_OBJECT DriverObject, 1038 IN PUNICODE_STRING RegPath) 1039 { 1040 /* initialize driver object */ 1041 DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create; 1042 DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close; 1043 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush; 1044 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl; 1045 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl; 1046 DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power; 1047 DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp; 1048 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KbdHid_SystemControl; 1049 DriverObject->DriverUnload = KbdHid_Unload; 1050 DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice; 1051 1052 /* done */ 1053 return STATUS_SUCCESS; 1054 } 1055