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