1 /* 2 * PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/hid/hidclass/hidclass.c 5 * PURPOSE: HID Class Driver 6 * PROGRAMMERS: 7 * Michael Martin (michael.martin@reactos.org) 8 * Johannes Anderwald (johannes.anderwald@reactos.org) 9 */ 10 11 #include "precomp.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 static LPWSTR ClientIdentificationAddress = L"HIDCLASS"; 17 static ULONG HidClassDeviceNumber = 0; 18 19 NTSTATUS 20 NTAPI 21 DllInitialize( 22 IN PUNICODE_STRING RegistryPath) 23 { 24 return STATUS_SUCCESS; 25 } 26 27 NTSTATUS 28 NTAPI 29 DllUnload(VOID) 30 { 31 return STATUS_SUCCESS; 32 } 33 34 NTSTATUS 35 NTAPI 36 HidClassAddDevice( 37 IN PDRIVER_OBJECT DriverObject, 38 IN PDEVICE_OBJECT PhysicalDeviceObject) 39 { 40 WCHAR CharDeviceName[64]; 41 NTSTATUS Status; 42 UNICODE_STRING DeviceName; 43 PDEVICE_OBJECT NewDeviceObject; 44 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 45 ULONG DeviceExtensionSize; 46 PHIDCLASS_DRIVER_EXTENSION DriverExtension; 47 48 /* increment device number */ 49 InterlockedIncrement((PLONG)&HidClassDeviceNumber); 50 51 /* construct device name */ 52 swprintf(CharDeviceName, L"\\Device\\_HID%08x", HidClassDeviceNumber); 53 54 /* initialize device name */ 55 RtlInitUnicodeString(&DeviceName, CharDeviceName); 56 57 /* get driver object extension */ 58 DriverExtension = IoGetDriverObjectExtension(DriverObject, ClientIdentificationAddress); 59 if (!DriverExtension) 60 { 61 /* device removed */ 62 ASSERT(FALSE); 63 return STATUS_DEVICE_CONFIGURATION_ERROR; 64 } 65 66 /* calculate device extension size */ 67 DeviceExtensionSize = sizeof(HIDCLASS_FDO_EXTENSION) + DriverExtension->DeviceExtensionSize; 68 69 /* now create the device */ 70 Status = IoCreateDevice(DriverObject, DeviceExtensionSize, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &NewDeviceObject); 71 if (!NT_SUCCESS(Status)) 72 { 73 /* failed to create device object */ 74 ASSERT(FALSE); 75 return Status; 76 } 77 78 /* get device extension */ 79 FDODeviceExtension = NewDeviceObject->DeviceExtension; 80 81 /* zero device extension */ 82 RtlZeroMemory(FDODeviceExtension, sizeof(HIDCLASS_FDO_EXTENSION)); 83 84 /* initialize device extension */ 85 FDODeviceExtension->Common.IsFDO = TRUE; 86 FDODeviceExtension->Common.DriverExtension = DriverExtension; 87 FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = PhysicalDeviceObject; 88 FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = (PVOID)((ULONG_PTR)FDODeviceExtension + sizeof(HIDCLASS_FDO_EXTENSION)); 89 FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = IoAttachDeviceToDeviceStack(NewDeviceObject, PhysicalDeviceObject); 90 if (FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject == NULL) 91 { 92 /* no PDO */ 93 IoDeleteDevice(NewDeviceObject); 94 DPRINT1("[HIDCLASS] failed to attach to device stack\n"); 95 return STATUS_DEVICE_REMOVED; 96 } 97 98 /* sanity check */ 99 ASSERT(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); 100 101 /* increment stack size */ 102 NewDeviceObject->StackSize++; 103 104 /* init device object */ 105 NewDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; 106 NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 107 108 /* now call driver provided add device routine */ 109 ASSERT(DriverExtension->AddDevice != 0); 110 Status = DriverExtension->AddDevice(DriverObject, NewDeviceObject); 111 if (!NT_SUCCESS(Status)) 112 { 113 /* failed */ 114 DPRINT1("HIDCLASS: AddDevice failed with %x\n", Status); 115 IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); 116 IoDeleteDevice(NewDeviceObject); 117 return Status; 118 } 119 120 /* succeeded */ 121 return Status; 122 } 123 124 VOID 125 NTAPI 126 HidClassDriverUnload( 127 IN PDRIVER_OBJECT DriverObject) 128 { 129 UNIMPLEMENTED; 130 } 131 132 NTSTATUS 133 NTAPI 134 HidClass_Create( 135 IN PDEVICE_OBJECT DeviceObject, 136 IN PIRP Irp) 137 { 138 PIO_STACK_LOCATION IoStack; 139 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 140 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; 141 PHIDCLASS_FILEOP_CONTEXT Context; 142 143 // 144 // get device extension 145 // 146 CommonDeviceExtension = DeviceObject->DeviceExtension; 147 if (CommonDeviceExtension->IsFDO) 148 { 149 // 150 // only supported for PDO 151 // 152 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 153 IoCompleteRequest(Irp, IO_NO_INCREMENT); 154 return STATUS_UNSUCCESSFUL; 155 } 156 157 // 158 // must be a PDO 159 // 160 ASSERT(CommonDeviceExtension->IsFDO == FALSE); 161 162 // 163 // get device extension 164 // 165 PDODeviceExtension = DeviceObject->DeviceExtension; 166 167 // 168 // get stack location 169 // 170 IoStack = IoGetCurrentIrpStackLocation(Irp); 171 172 DPRINT("ShareAccess %x\n", IoStack->Parameters.Create.ShareAccess); 173 DPRINT("Options %x\n", IoStack->Parameters.Create.Options); 174 DPRINT("DesiredAccess %x\n", IoStack->Parameters.Create.SecurityContext->DesiredAccess); 175 176 // 177 // allocate context 178 // 179 Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(HIDCLASS_FILEOP_CONTEXT), HIDCLASS_TAG); 180 if (!Context) 181 { 182 // 183 // no memory 184 // 185 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 186 IoCompleteRequest(Irp, IO_NO_INCREMENT); 187 return STATUS_INSUFFICIENT_RESOURCES; 188 } 189 190 // 191 // init context 192 // 193 RtlZeroMemory(Context, sizeof(HIDCLASS_FILEOP_CONTEXT)); 194 Context->DeviceExtension = PDODeviceExtension; 195 KeInitializeSpinLock(&Context->Lock); 196 InitializeListHead(&Context->ReadPendingIrpListHead); 197 InitializeListHead(&Context->IrpCompletedListHead); 198 KeInitializeEvent(&Context->IrpReadComplete, NotificationEvent, FALSE); 199 200 // 201 // store context 202 // 203 ASSERT(IoStack->FileObject); 204 IoStack->FileObject->FsContext = Context; 205 206 // 207 // done 208 // 209 Irp->IoStatus.Status = STATUS_SUCCESS; 210 IoCompleteRequest(Irp, IO_NO_INCREMENT); 211 return STATUS_SUCCESS; 212 } 213 214 NTSTATUS 215 NTAPI 216 HidClass_Close( 217 IN PDEVICE_OBJECT DeviceObject, 218 IN PIRP Irp) 219 { 220 PIO_STACK_LOCATION IoStack; 221 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 222 PHIDCLASS_FILEOP_CONTEXT IrpContext; 223 BOOLEAN IsRequestPending = FALSE; 224 KIRQL OldLevel; 225 PLIST_ENTRY Entry; 226 PIRP ListIrp; 227 228 // 229 // get device extension 230 // 231 CommonDeviceExtension = DeviceObject->DeviceExtension; 232 233 // 234 // is it a FDO request 235 // 236 if (CommonDeviceExtension->IsFDO) 237 { 238 // 239 // how did the request get there 240 // 241 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER_1; 242 IoCompleteRequest(Irp, IO_NO_INCREMENT); 243 return STATUS_INVALID_PARAMETER_1; 244 } 245 246 // 247 // get stack location 248 // 249 IoStack = IoGetCurrentIrpStackLocation(Irp); 250 251 // 252 // sanity checks 253 // 254 ASSERT(IoStack->FileObject); 255 ASSERT(IoStack->FileObject->FsContext); 256 257 // 258 // get irp context 259 // 260 IrpContext = IoStack->FileObject->FsContext; 261 ASSERT(IrpContext); 262 263 // 264 // acquire lock 265 // 266 KeAcquireSpinLock(&IrpContext->Lock, &OldLevel); 267 268 if (!IsListEmpty(&IrpContext->ReadPendingIrpListHead)) 269 { 270 // 271 // FIXME cancel irp 272 // 273 IsRequestPending = TRUE; 274 } 275 276 // 277 // signal stop 278 // 279 IrpContext->StopInProgress = TRUE; 280 281 // 282 // release lock 283 // 284 KeReleaseSpinLock(&IrpContext->Lock, OldLevel); 285 286 if (IsRequestPending) 287 { 288 // 289 // wait for request to complete 290 // 291 DPRINT1("[HIDCLASS] Waiting for read irp completion...\n"); 292 KeWaitForSingleObject(&IrpContext->IrpReadComplete, Executive, KernelMode, FALSE, NULL); 293 } 294 295 // 296 // acquire lock 297 // 298 KeAcquireSpinLock(&IrpContext->Lock, &OldLevel); 299 300 // 301 // sanity check 302 // 303 ASSERT(IsListEmpty(&IrpContext->ReadPendingIrpListHead)); 304 305 // 306 // now free all irps 307 // 308 while (!IsListEmpty(&IrpContext->IrpCompletedListHead)) 309 { 310 // 311 // remove head irp 312 // 313 Entry = RemoveHeadList(&IrpContext->IrpCompletedListHead); 314 315 // 316 // get irp 317 // 318 ListIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 319 320 // 321 // free the irp 322 // 323 IoFreeIrp(ListIrp); 324 } 325 326 // 327 // release lock 328 // 329 KeReleaseSpinLock(&IrpContext->Lock, OldLevel); 330 331 // 332 // remove context 333 // 334 IoStack->FileObject->FsContext = NULL; 335 336 // 337 // free context 338 // 339 ExFreePoolWithTag(IrpContext, HIDCLASS_TAG); 340 341 // 342 // complete request 343 // 344 Irp->IoStatus.Status = STATUS_SUCCESS; 345 IoCompleteRequest(Irp, IO_NO_INCREMENT); 346 return STATUS_SUCCESS; 347 } 348 349 NTSTATUS 350 NTAPI 351 HidClass_ReadCompleteIrp( 352 IN PDEVICE_OBJECT DeviceObject, 353 IN PIRP Irp, 354 IN PVOID Ctx) 355 { 356 PHIDCLASS_IRP_CONTEXT IrpContext; 357 KIRQL OldLevel; 358 PUCHAR Address; 359 ULONG Offset; 360 PHIDP_COLLECTION_DESC CollectionDescription; 361 PHIDP_REPORT_IDS ReportDescription; 362 BOOLEAN IsEmpty; 363 364 // 365 // get irp context 366 // 367 IrpContext = Ctx; 368 369 DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql()); 370 DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp->IoStatus.Status); 371 DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp->IoStatus.Information); 372 DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp); 373 DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext->InputReportBuffer); 374 DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext->InputReportBufferLength); 375 DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext->OriginalIrp); 376 377 // 378 // copy result 379 // 380 if (Irp->IoStatus.Information) 381 { 382 // 383 // get address 384 // 385 Address = MmGetSystemAddressForMdlSafe(IrpContext->OriginalIrp->MdlAddress, NormalPagePriority); 386 if (Address) 387 { 388 // 389 // reports may have a report id prepended 390 // 391 Offset = 0; 392 393 // 394 // get collection description 395 // 396 CollectionDescription = HidClassPDO_GetCollectionDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, 397 IrpContext->FileOp->DeviceExtension->CollectionNumber); 398 ASSERT(CollectionDescription); 399 400 // 401 // get report description 402 // 403 ReportDescription = HidClassPDO_GetReportDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, 404 IrpContext->FileOp->DeviceExtension->CollectionNumber); 405 ASSERT(ReportDescription); 406 407 if (CollectionDescription && ReportDescription) 408 { 409 // 410 // calculate offset 411 // 412 ASSERT(CollectionDescription->InputLength >= ReportDescription->InputLength); 413 Offset = CollectionDescription->InputLength - ReportDescription->InputLength; 414 } 415 416 // 417 // copy result 418 // 419 RtlCopyMemory(&Address[Offset], IrpContext->InputReportBuffer, IrpContext->InputReportBufferLength); 420 } 421 } 422 423 // 424 // copy result status 425 // 426 IrpContext->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status; 427 IrpContext->OriginalIrp->IoStatus.Information = Irp->IoStatus.Information; 428 429 // 430 // free input report buffer 431 // 432 ExFreePoolWithTag(IrpContext->InputReportBuffer, HIDCLASS_TAG); 433 434 // 435 // remove us from pending list 436 // 437 KeAcquireSpinLock(&IrpContext->FileOp->Lock, &OldLevel); 438 439 // 440 // remove from pending list 441 // 442 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 443 444 // 445 // is list empty 446 // 447 IsEmpty = IsListEmpty(&IrpContext->FileOp->ReadPendingIrpListHead); 448 449 // 450 // insert into completed list 451 // 452 InsertTailList(&IrpContext->FileOp->IrpCompletedListHead, &Irp->Tail.Overlay.ListEntry); 453 454 // 455 // release lock 456 // 457 KeReleaseSpinLock(&IrpContext->FileOp->Lock, OldLevel); 458 459 // 460 // complete original request 461 // 462 IoCompleteRequest(IrpContext->OriginalIrp, IO_NO_INCREMENT); 463 464 465 DPRINT("StopInProgress %x IsEmpty %x\n", IrpContext->FileOp->StopInProgress, IsEmpty); 466 if (IrpContext->FileOp->StopInProgress && IsEmpty) 467 { 468 // 469 // last pending irp 470 // 471 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n"); 472 KeSetEvent(&IrpContext->FileOp->IrpReadComplete, 0, FALSE); 473 } 474 475 if (IrpContext->FileOp->StopInProgress && IsEmpty) 476 { 477 // 478 // last pending irp 479 // 480 DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n"); 481 KeSetEvent(&IrpContext->FileOp->IrpReadComplete, 0, FALSE); 482 } 483 484 // 485 // free irp context 486 // 487 ExFreePoolWithTag(IrpContext, HIDCLASS_TAG); 488 489 // 490 // done 491 // 492 return STATUS_MORE_PROCESSING_REQUIRED; 493 } 494 495 PIRP 496 HidClass_GetIrp( 497 IN PHIDCLASS_FILEOP_CONTEXT Context) 498 { 499 KIRQL OldLevel; 500 PIRP Irp = NULL; 501 PLIST_ENTRY ListEntry; 502 503 // 504 // acquire lock 505 // 506 KeAcquireSpinLock(&Context->Lock, &OldLevel); 507 508 // 509 // is list empty? 510 // 511 if (!IsListEmpty(&Context->IrpCompletedListHead)) 512 { 513 // 514 // grab first entry 515 // 516 ListEntry = RemoveHeadList(&Context->IrpCompletedListHead); 517 518 // 519 // get irp 520 // 521 Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry); 522 } 523 524 // 525 // release lock 526 // 527 KeReleaseSpinLock(&Context->Lock, OldLevel); 528 529 // 530 // done 531 // 532 return Irp; 533 } 534 535 NTSTATUS 536 HidClass_BuildIrp( 537 IN PDEVICE_OBJECT DeviceObject, 538 IN PIRP RequestIrp, 539 IN PHIDCLASS_FILEOP_CONTEXT Context, 540 IN ULONG DeviceIoControlCode, 541 IN ULONG BufferLength, 542 OUT PIRP *OutIrp, 543 OUT PHIDCLASS_IRP_CONTEXT *OutIrpContext) 544 { 545 PIRP Irp; 546 PIO_STACK_LOCATION IoStack; 547 PHIDCLASS_IRP_CONTEXT IrpContext; 548 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; 549 PHIDP_COLLECTION_DESC CollectionDescription; 550 PHIDP_REPORT_IDS ReportDescription; 551 552 // 553 // get an irp from fresh list 554 // 555 Irp = HidClass_GetIrp(Context); 556 if (!Irp) 557 { 558 // 559 // build new irp 560 // 561 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 562 if (!Irp) 563 { 564 // 565 // no memory 566 // 567 return STATUS_INSUFFICIENT_RESOURCES; 568 } 569 } 570 else 571 { 572 // 573 // re-use irp 574 // 575 IoReuseIrp(Irp, STATUS_SUCCESS); 576 } 577 578 // 579 // allocate completion context 580 // 581 IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(HIDCLASS_IRP_CONTEXT), HIDCLASS_TAG); 582 if (!IrpContext) 583 { 584 // 585 // no memory 586 // 587 IoFreeIrp(Irp); 588 return STATUS_INSUFFICIENT_RESOURCES; 589 } 590 591 // 592 // get device extension 593 // 594 PDODeviceExtension = DeviceObject->DeviceExtension; 595 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 596 597 // 598 // init irp context 599 // 600 RtlZeroMemory(IrpContext, sizeof(HIDCLASS_IRP_CONTEXT)); 601 IrpContext->OriginalIrp = RequestIrp; 602 IrpContext->FileOp = Context; 603 604 // 605 // get collection description 606 // 607 CollectionDescription = HidClassPDO_GetCollectionDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, 608 IrpContext->FileOp->DeviceExtension->CollectionNumber); 609 ASSERT(CollectionDescription); 610 611 // 612 // get report description 613 // 614 ReportDescription = HidClassPDO_GetReportDescription(&IrpContext->FileOp->DeviceExtension->Common.DeviceDescription, 615 IrpContext->FileOp->DeviceExtension->CollectionNumber); 616 ASSERT(ReportDescription); 617 618 // 619 // sanity check 620 // 621 ASSERT(CollectionDescription->InputLength >= ReportDescription->InputLength); 622 623 if (Context->StopInProgress) 624 { 625 // 626 // stop in progress 627 // 628 DPRINT1("[HIDCLASS] Stop In Progress\n"); 629 Irp->IoStatus.Status = STATUS_CANCELLED; 630 IoCompleteRequest(Irp, IO_NO_INCREMENT); 631 return STATUS_CANCELLED; 632 633 } 634 635 // 636 // store report length 637 // 638 IrpContext->InputReportBufferLength = ReportDescription->InputLength; 639 640 // 641 // allocate buffer 642 // 643 IrpContext->InputReportBuffer = ExAllocatePoolWithTag(NonPagedPool, IrpContext->InputReportBufferLength, HIDCLASS_TAG); 644 if (!IrpContext->InputReportBuffer) 645 { 646 // 647 // no memory 648 // 649 IoFreeIrp(Irp); 650 ExFreePoolWithTag(IrpContext, HIDCLASS_TAG); 651 return STATUS_INSUFFICIENT_RESOURCES; 652 } 653 654 // 655 // get stack location 656 // 657 IoStack = IoGetNextIrpStackLocation(Irp); 658 659 // 660 // init stack location 661 // 662 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 663 IoStack->Parameters.DeviceIoControl.IoControlCode = DeviceIoControlCode; 664 IoStack->Parameters.DeviceIoControl.OutputBufferLength = IrpContext->InputReportBufferLength; 665 IoStack->Parameters.DeviceIoControl.InputBufferLength = 0; 666 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL; 667 Irp->UserBuffer = IrpContext->InputReportBuffer; 668 IoStack->DeviceObject = DeviceObject; 669 670 // 671 // store result 672 // 673 *OutIrp = Irp; 674 *OutIrpContext = IrpContext; 675 676 // 677 // done 678 // 679 return STATUS_SUCCESS; 680 } 681 682 NTSTATUS 683 NTAPI 684 HidClass_Read( 685 IN PDEVICE_OBJECT DeviceObject, 686 IN PIRP Irp) 687 { 688 PIO_STACK_LOCATION IoStack; 689 PHIDCLASS_FILEOP_CONTEXT Context; 690 KIRQL OldLevel; 691 NTSTATUS Status; 692 PIRP NewIrp; 693 PHIDCLASS_IRP_CONTEXT NewIrpContext; 694 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 695 696 // 697 // get current stack location 698 // 699 IoStack = IoGetCurrentIrpStackLocation(Irp); 700 701 // 702 // get device extension 703 // 704 CommonDeviceExtension = DeviceObject->DeviceExtension; 705 ASSERT(CommonDeviceExtension->IsFDO == FALSE); 706 707 // 708 // sanity check 709 // 710 ASSERT(IoStack->FileObject); 711 ASSERT(IoStack->FileObject->FsContext); 712 713 // 714 // get context 715 // 716 Context = IoStack->FileObject->FsContext; 717 ASSERT(Context); 718 719 // 720 // FIXME support polled devices 721 // 722 ASSERT(Context->DeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE); 723 724 if (Context->StopInProgress) 725 { 726 // 727 // stop in progress 728 // 729 DPRINT1("[HIDCLASS] Stop In Progress\n"); 730 Irp->IoStatus.Status = STATUS_CANCELLED; 731 IoCompleteRequest(Irp, IO_NO_INCREMENT); 732 return STATUS_CANCELLED; 733 } 734 735 // 736 // build irp request 737 // 738 Status = HidClass_BuildIrp(DeviceObject, 739 Irp, 740 Context, 741 IOCTL_HID_READ_REPORT, 742 IoStack->Parameters.Read.Length, 743 &NewIrp, 744 &NewIrpContext); 745 if (!NT_SUCCESS(Status)) 746 { 747 // 748 // failed 749 // 750 DPRINT1("HidClass_BuildIrp failed with %x\n", Status); 751 Irp->IoStatus.Status = Status; 752 IoCompleteRequest(Irp, IO_NO_INCREMENT); 753 return Status; 754 } 755 756 // 757 // acquire lock 758 // 759 KeAcquireSpinLock(&Context->Lock, &OldLevel); 760 761 // 762 // insert irp into pending list 763 // 764 InsertTailList(&Context->ReadPendingIrpListHead, &NewIrp->Tail.Overlay.ListEntry); 765 766 // 767 // set completion routine 768 // 769 IoSetCompletionRoutine(NewIrp, HidClass_ReadCompleteIrp, NewIrpContext, TRUE, TRUE, TRUE); 770 771 // 772 // make next location current 773 // 774 IoSetNextIrpStackLocation(NewIrp); 775 776 // 777 // release spin lock 778 // 779 KeReleaseSpinLock(&Context->Lock, OldLevel); 780 781 // 782 // mark irp pending 783 // 784 IoMarkIrpPending(Irp); 785 786 // 787 // let's dispatch the request 788 // 789 ASSERT(Context->DeviceExtension); 790 Status = Context->DeviceExtension->Common.DriverExtension->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL](Context->DeviceExtension->FDODeviceObject, NewIrp); 791 792 // 793 // complete 794 // 795 return STATUS_PENDING; 796 } 797 798 NTSTATUS 799 NTAPI 800 HidClass_Write( 801 IN PDEVICE_OBJECT DeviceObject, 802 IN PIRP Irp) 803 { 804 PIO_STACK_LOCATION IoStack; 805 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 806 PIRP SubIrp; 807 KEVENT Event; 808 IO_STATUS_BLOCK IoStatusBlock; 809 HID_XFER_PACKET XferPacket; 810 NTSTATUS Status; 811 ULONG Length; 812 813 IoStack = IoGetCurrentIrpStackLocation(Irp); 814 Length = IoStack->Parameters.Write.Length; 815 if (Length < 1) 816 { 817 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 818 IoCompleteRequest(Irp, IO_NO_INCREMENT); 819 return STATUS_INVALID_PARAMETER; 820 } 821 822 RtlZeroMemory(&XferPacket, sizeof(XferPacket)); 823 XferPacket.reportBufferLen = Length; 824 XferPacket.reportBuffer = Irp->UserBuffer; 825 XferPacket.reportId = XferPacket.reportBuffer[0]; 826 827 CommonDeviceExtension = DeviceObject->DeviceExtension; 828 SubIrp = IoBuildDeviceIoControlRequest( 829 IOCTL_HID_WRITE_REPORT, 830 CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, 831 NULL, 0, 832 NULL, 0, 833 TRUE, 834 &Event, 835 &IoStatusBlock); 836 if (!SubIrp) 837 { 838 Irp->IoStatus.Status = STATUS_NO_MEMORY; 839 IoCompleteRequest(Irp, IO_NO_INCREMENT); 840 return STATUS_NOT_IMPLEMENTED; 841 } 842 SubIrp->UserBuffer = &XferPacket; 843 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 844 Status = IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, SubIrp); 845 if (Status == STATUS_PENDING) 846 { 847 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 848 Status = IoStatusBlock.Status; 849 } 850 Irp->IoStatus.Status = Status; 851 IoCompleteRequest(Irp, IO_NO_INCREMENT); 852 return Status; 853 } 854 855 NTSTATUS 856 NTAPI 857 HidClass_DeviceControl( 858 IN PDEVICE_OBJECT DeviceObject, 859 IN PIRP Irp) 860 { 861 PIO_STACK_LOCATION IoStack; 862 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 863 PHID_COLLECTION_INFORMATION CollectionInformation; 864 PHIDP_COLLECTION_DESC CollectionDescription; 865 PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; 866 867 // 868 // get device extension 869 // 870 CommonDeviceExtension = DeviceObject->DeviceExtension; 871 872 // 873 // only PDO are supported 874 // 875 if (CommonDeviceExtension->IsFDO) 876 { 877 // 878 // invalid request 879 // 880 DPRINT1("[HIDCLASS] DeviceControl Irp for FDO arrived\n"); 881 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER_1; 882 IoCompleteRequest(Irp, IO_NO_INCREMENT); 883 return STATUS_INVALID_PARAMETER_1; 884 } 885 886 ASSERT(CommonDeviceExtension->IsFDO == FALSE); 887 888 // 889 // get pdo device extension 890 // 891 PDODeviceExtension = DeviceObject->DeviceExtension; 892 893 // 894 // get stack location 895 // 896 IoStack = IoGetCurrentIrpStackLocation(Irp); 897 898 switch (IoStack->Parameters.DeviceIoControl.IoControlCode) 899 { 900 case IOCTL_HID_GET_COLLECTION_INFORMATION: 901 { 902 // 903 // check if output buffer is big enough 904 // 905 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_COLLECTION_INFORMATION)) 906 { 907 // 908 // invalid buffer size 909 // 910 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; 911 IoCompleteRequest(Irp, IO_NO_INCREMENT); 912 return STATUS_INVALID_BUFFER_SIZE; 913 } 914 915 // 916 // get output buffer 917 // 918 CollectionInformation = Irp->AssociatedIrp.SystemBuffer; 919 ASSERT(CollectionInformation); 920 921 // 922 // get collection description 923 // 924 CollectionDescription = HidClassPDO_GetCollectionDescription(&CommonDeviceExtension->DeviceDescription, 925 PDODeviceExtension->CollectionNumber); 926 ASSERT(CollectionDescription); 927 928 // 929 // init result buffer 930 // 931 CollectionInformation->DescriptorSize = CollectionDescription->PreparsedDataLength; 932 CollectionInformation->Polled = CommonDeviceExtension->DriverExtension->DevicesArePolled; 933 CollectionInformation->VendorID = CommonDeviceExtension->Attributes.VendorID; 934 CollectionInformation->ProductID = CommonDeviceExtension->Attributes.ProductID; 935 CollectionInformation->VersionNumber = CommonDeviceExtension->Attributes.VersionNumber; 936 937 // 938 // complete request 939 // 940 Irp->IoStatus.Information = sizeof(HID_COLLECTION_INFORMATION); 941 Irp->IoStatus.Status = STATUS_SUCCESS; 942 IoCompleteRequest(Irp, IO_NO_INCREMENT); 943 return STATUS_SUCCESS; 944 } 945 case IOCTL_HID_GET_COLLECTION_DESCRIPTOR: 946 { 947 // 948 // get collection description 949 // 950 CollectionDescription = HidClassPDO_GetCollectionDescription(&CommonDeviceExtension->DeviceDescription, 951 PDODeviceExtension->CollectionNumber); 952 ASSERT(CollectionDescription); 953 954 // 955 // check if output buffer is big enough 956 // 957 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < CollectionDescription->PreparsedDataLength) 958 { 959 // 960 // invalid buffer size 961 // 962 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; 963 IoCompleteRequest(Irp, IO_NO_INCREMENT); 964 return STATUS_INVALID_BUFFER_SIZE; 965 } 966 967 // 968 // copy result 969 // 970 ASSERT(Irp->UserBuffer); 971 RtlCopyMemory(Irp->UserBuffer, CollectionDescription->PreparsedData, CollectionDescription->PreparsedDataLength); 972 973 // 974 // complete request 975 // 976 Irp->IoStatus.Information = CollectionDescription->PreparsedDataLength; 977 Irp->IoStatus.Status = STATUS_SUCCESS; 978 IoCompleteRequest(Irp, IO_NO_INCREMENT); 979 return STATUS_SUCCESS; 980 } 981 case IOCTL_HID_GET_FEATURE: 982 { 983 PIRP SubIrp; 984 KEVENT Event; 985 IO_STATUS_BLOCK IoStatusBlock; 986 HID_XFER_PACKET XferPacket; 987 NTSTATUS Status; 988 PHIDP_REPORT_IDS ReportDescription; 989 990 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < 1) 991 { 992 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 993 IoCompleteRequest(Irp, IO_NO_INCREMENT); 994 return STATUS_INVALID_PARAMETER; 995 } 996 ReportDescription = HidClassPDO_GetReportDescriptionByReportID(&PDODeviceExtension->Common.DeviceDescription, ((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0]); 997 if (!ReportDescription || IoStack->Parameters.DeviceIoControl.OutputBufferLength < ReportDescription->FeatureLength) 998 { 999 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1000 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1001 return STATUS_INVALID_PARAMETER; 1002 } 1003 1004 RtlZeroMemory(&XferPacket, sizeof(XferPacket)); 1005 XferPacket.reportBufferLen = ReportDescription->FeatureLength; 1006 XferPacket.reportBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 1007 XferPacket.reportId = ((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0]; 1008 if (!XferPacket.reportBuffer) 1009 { 1010 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1011 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1012 return STATUS_INSUFFICIENT_RESOURCES; 1013 } 1014 1015 SubIrp = IoBuildDeviceIoControlRequest( 1016 IOCTL_HID_GET_FEATURE, 1017 CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, 1018 NULL, 0, 1019 NULL, 0, 1020 TRUE, 1021 &Event, 1022 &IoStatusBlock); 1023 if (!SubIrp) 1024 { 1025 Irp->IoStatus.Status = STATUS_NO_MEMORY; 1026 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1027 return STATUS_NOT_IMPLEMENTED; 1028 } 1029 SubIrp->UserBuffer = &XferPacket; 1030 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 1031 Status = IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, SubIrp); 1032 if (Status == STATUS_PENDING) 1033 { 1034 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1035 Status = IoStatusBlock.Status; 1036 } 1037 Irp->IoStatus.Status = Status; 1038 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1039 return Status; 1040 } 1041 case IOCTL_HID_SET_FEATURE: 1042 { 1043 PIRP SubIrp; 1044 KEVENT Event; 1045 IO_STATUS_BLOCK IoStatusBlock; 1046 HID_XFER_PACKET XferPacket; 1047 NTSTATUS Status; 1048 PHIDP_REPORT_IDS ReportDescription; 1049 1050 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < 1) 1051 { 1052 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1053 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1054 return STATUS_INVALID_PARAMETER; 1055 } 1056 ReportDescription = HidClassPDO_GetReportDescriptionByReportID(&PDODeviceExtension->Common.DeviceDescription, ((PUCHAR)Irp->AssociatedIrp.SystemBuffer)[0]); 1057 if (!ReportDescription || IoStack->Parameters.DeviceIoControl.InputBufferLength < ReportDescription->FeatureLength) 1058 { 1059 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1060 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1061 return STATUS_INVALID_PARAMETER; 1062 } 1063 1064 RtlZeroMemory(&XferPacket, sizeof(XferPacket)); 1065 XferPacket.reportBufferLen = ReportDescription->FeatureLength; 1066 XferPacket.reportBuffer = Irp->AssociatedIrp.SystemBuffer; 1067 XferPacket.reportId = XferPacket.reportBuffer[0]; 1068 1069 SubIrp = IoBuildDeviceIoControlRequest( 1070 IOCTL_HID_SET_FEATURE, 1071 CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, 1072 NULL, 0, 1073 NULL, 0, 1074 TRUE, 1075 &Event, 1076 &IoStatusBlock); 1077 if (!SubIrp) 1078 { 1079 Irp->IoStatus.Status = STATUS_NO_MEMORY; 1080 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1081 return STATUS_NOT_IMPLEMENTED; 1082 } 1083 SubIrp->UserBuffer = &XferPacket; 1084 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 1085 Status = IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, SubIrp); 1086 if (Status == STATUS_PENDING) 1087 { 1088 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1089 Status = IoStatusBlock.Status; 1090 } 1091 Irp->IoStatus.Status = Status; 1092 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1093 return Status; 1094 } 1095 default: 1096 { 1097 DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack->Parameters.DeviceIoControl.IoControlCode); 1098 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 1099 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1100 return STATUS_NOT_IMPLEMENTED; 1101 } 1102 } 1103 } 1104 1105 NTSTATUS 1106 NTAPI 1107 HidClass_InternalDeviceControl( 1108 IN PDEVICE_OBJECT DeviceObject, 1109 IN PIRP Irp) 1110 { 1111 UNIMPLEMENTED; 1112 ASSERT(FALSE); 1113 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 1114 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1115 return STATUS_NOT_IMPLEMENTED; 1116 } 1117 1118 NTSTATUS 1119 NTAPI 1120 HidClass_Power( 1121 IN PDEVICE_OBJECT DeviceObject, 1122 IN PIRP Irp) 1123 { 1124 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 1125 CommonDeviceExtension = DeviceObject->DeviceExtension; 1126 1127 if (CommonDeviceExtension->IsFDO) 1128 { 1129 IoCopyCurrentIrpStackLocationToNext(Irp); 1130 return HidClassFDO_DispatchRequest(DeviceObject, Irp); 1131 } 1132 else 1133 { 1134 Irp->IoStatus.Status = STATUS_SUCCESS; 1135 PoStartNextPowerIrp(Irp); 1136 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1137 return STATUS_SUCCESS; 1138 } 1139 } 1140 1141 NTSTATUS 1142 NTAPI 1143 HidClass_PnP( 1144 IN PDEVICE_OBJECT DeviceObject, 1145 IN PIRP Irp) 1146 { 1147 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 1148 1149 // 1150 // get common device extension 1151 // 1152 CommonDeviceExtension = DeviceObject->DeviceExtension; 1153 1154 // 1155 // check type of device object 1156 // 1157 if (CommonDeviceExtension->IsFDO) 1158 { 1159 // 1160 // handle request 1161 // 1162 return HidClassFDO_PnP(DeviceObject, Irp); 1163 } 1164 else 1165 { 1166 // 1167 // handle request 1168 // 1169 return HidClassPDO_PnP(DeviceObject, Irp); 1170 } 1171 } 1172 1173 NTSTATUS 1174 NTAPI 1175 HidClass_DispatchDefault( 1176 IN PDEVICE_OBJECT DeviceObject, 1177 IN PIRP Irp) 1178 { 1179 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 1180 1181 // 1182 // get common device extension 1183 // 1184 CommonDeviceExtension = DeviceObject->DeviceExtension; 1185 1186 // 1187 // FIXME: support PDO 1188 // 1189 ASSERT(CommonDeviceExtension->IsFDO == TRUE); 1190 1191 // 1192 // skip current irp stack location 1193 // 1194 IoSkipCurrentIrpStackLocation(Irp); 1195 1196 // 1197 // dispatch to lower device object 1198 // 1199 return IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, Irp); 1200 } 1201 1202 NTSTATUS 1203 NTAPI 1204 HidClassDispatch( 1205 IN PDEVICE_OBJECT DeviceObject, 1206 IN PIRP Irp) 1207 { 1208 PIO_STACK_LOCATION IoStack; 1209 1210 // 1211 // get current stack location 1212 // 1213 IoStack = IoGetCurrentIrpStackLocation(Irp); 1214 DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack->MajorFunction, IoStack->MinorFunction); 1215 1216 // 1217 // dispatch request based on major function 1218 // 1219 switch (IoStack->MajorFunction) 1220 { 1221 case IRP_MJ_CREATE: 1222 return HidClass_Create(DeviceObject, Irp); 1223 case IRP_MJ_CLOSE: 1224 return HidClass_Close(DeviceObject, Irp); 1225 case IRP_MJ_READ: 1226 return HidClass_Read(DeviceObject, Irp); 1227 case IRP_MJ_WRITE: 1228 return HidClass_Write(DeviceObject, Irp); 1229 case IRP_MJ_DEVICE_CONTROL: 1230 return HidClass_DeviceControl(DeviceObject, Irp); 1231 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 1232 return HidClass_InternalDeviceControl(DeviceObject, Irp); 1233 case IRP_MJ_POWER: 1234 return HidClass_Power(DeviceObject, Irp); 1235 case IRP_MJ_PNP: 1236 return HidClass_PnP(DeviceObject, Irp); 1237 default: 1238 return HidClass_DispatchDefault(DeviceObject, Irp); 1239 } 1240 } 1241 1242 NTSTATUS 1243 NTAPI 1244 HidRegisterMinidriver( 1245 IN PHID_MINIDRIVER_REGISTRATION MinidriverRegistration) 1246 { 1247 NTSTATUS Status; 1248 PHIDCLASS_DRIVER_EXTENSION DriverExtension; 1249 1250 /* check if the version matches */ 1251 if (MinidriverRegistration->Revision > HID_REVISION) 1252 { 1253 /* revision mismatch */ 1254 ASSERT(FALSE); 1255 return STATUS_REVISION_MISMATCH; 1256 } 1257 1258 /* now allocate the driver object extension */ 1259 Status = IoAllocateDriverObjectExtension(MinidriverRegistration->DriverObject, 1260 ClientIdentificationAddress, 1261 sizeof(HIDCLASS_DRIVER_EXTENSION), 1262 (PVOID *)&DriverExtension); 1263 if (!NT_SUCCESS(Status)) 1264 { 1265 /* failed to allocate driver extension */ 1266 ASSERT(FALSE); 1267 return Status; 1268 } 1269 1270 /* zero driver extension */ 1271 RtlZeroMemory(DriverExtension, sizeof(HIDCLASS_DRIVER_EXTENSION)); 1272 1273 /* init driver extension */ 1274 DriverExtension->DriverObject = MinidriverRegistration->DriverObject; 1275 DriverExtension->DeviceExtensionSize = MinidriverRegistration->DeviceExtensionSize; 1276 DriverExtension->DevicesArePolled = MinidriverRegistration->DevicesArePolled; 1277 DriverExtension->AddDevice = MinidriverRegistration->DriverObject->DriverExtension->AddDevice; 1278 DriverExtension->DriverUnload = MinidriverRegistration->DriverObject->DriverUnload; 1279 1280 /* copy driver dispatch routines */ 1281 RtlCopyMemory(DriverExtension->MajorFunction, 1282 MinidriverRegistration->DriverObject->MajorFunction, 1283 sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1)); 1284 1285 /* initialize lock */ 1286 KeInitializeSpinLock(&DriverExtension->Lock); 1287 1288 /* now replace dispatch routines */ 1289 DriverExtension->DriverObject->DriverExtension->AddDevice = HidClassAddDevice; 1290 DriverExtension->DriverObject->DriverUnload = HidClassDriverUnload; 1291 DriverExtension->DriverObject->MajorFunction[IRP_MJ_CREATE] = HidClassDispatch; 1292 DriverExtension->DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidClassDispatch; 1293 DriverExtension->DriverObject->MajorFunction[IRP_MJ_READ] = HidClassDispatch; 1294 DriverExtension->DriverObject->MajorFunction[IRP_MJ_WRITE] = HidClassDispatch; 1295 DriverExtension->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidClassDispatch; 1296 DriverExtension->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidClassDispatch; 1297 DriverExtension->DriverObject->MajorFunction[IRP_MJ_POWER] = HidClassDispatch; 1298 DriverExtension->DriverObject->MajorFunction[IRP_MJ_PNP] = HidClassDispatch; 1299 1300 /* done */ 1301 return STATUS_SUCCESS; 1302 } 1303