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/fdo.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 NTSTATUS 17 NTAPI 18 HidClassFDO_QueryCapabilitiesCompletionRoutine( 19 IN PDEVICE_OBJECT DeviceObject, 20 IN PIRP Irp, 21 IN PVOID Context) 22 { 23 // 24 // set event 25 // 26 KeSetEvent(Context, 0, FALSE); 27 28 // 29 // completion is done in the HidClassFDO_QueryCapabilities routine 30 // 31 return STATUS_MORE_PROCESSING_REQUIRED; 32 } 33 34 NTSTATUS 35 HidClassFDO_QueryCapabilities( 36 IN PDEVICE_OBJECT DeviceObject, 37 IN OUT PDEVICE_CAPABILITIES Capabilities) 38 { 39 PIRP Irp; 40 KEVENT Event; 41 NTSTATUS Status; 42 PIO_STACK_LOCATION IoStack; 43 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 44 45 // 46 // get device extension 47 // 48 FDODeviceExtension = DeviceObject->DeviceExtension; 49 ASSERT(FDODeviceExtension->Common.IsFDO); 50 51 // 52 // init event 53 // 54 KeInitializeEvent(&Event, NotificationEvent, FALSE); 55 56 // 57 // now allocate the irp 58 // 59 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 60 if (!Irp) 61 { 62 // 63 // no memory 64 // 65 return STATUS_INSUFFICIENT_RESOURCES; 66 } 67 68 // 69 // get next stack location 70 // 71 IoStack = IoGetNextIrpStackLocation(Irp); 72 73 // 74 // init stack location 75 // 76 IoStack->MajorFunction = IRP_MJ_PNP; 77 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES; 78 IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities; 79 80 // 81 // set completion routine 82 // 83 IoSetCompletionRoutine(Irp, HidClassFDO_QueryCapabilitiesCompletionRoutine, &Event, TRUE, TRUE, TRUE); 84 85 // 86 // init capabilities 87 // 88 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); 89 Capabilities->Size = sizeof(DEVICE_CAPABILITIES); 90 Capabilities->Version = 1; // FIXME hardcoded constant 91 Capabilities->Address = MAXULONG; 92 Capabilities->UINumber = MAXULONG; 93 94 // 95 // pnp irps have default completion code 96 // 97 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 98 99 // 100 // call lower device 101 // 102 Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); 103 if (Status == STATUS_PENDING) 104 { 105 // 106 // wait for completion 107 // 108 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 109 } 110 111 // 112 // get status 113 // 114 Status = Irp->IoStatus.Status; 115 116 // 117 // complete request 118 // 119 IoFreeIrp(Irp); 120 121 // 122 // done 123 // 124 return Status; 125 } 126 127 NTSTATUS 128 NTAPI 129 HidClassFDO_DispatchRequestSynchronousCompletion( 130 IN PDEVICE_OBJECT DeviceObject, 131 IN PIRP Irp, 132 IN PVOID Context) 133 { 134 // 135 // signal event 136 // 137 KeSetEvent(Context, 0, FALSE); 138 139 // 140 // done 141 // 142 return STATUS_MORE_PROCESSING_REQUIRED; 143 } 144 145 146 NTSTATUS 147 HidClassFDO_DispatchRequestSynchronous( 148 IN PDEVICE_OBJECT DeviceObject, 149 IN PIRP Irp) 150 { 151 KEVENT Event; 152 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 153 NTSTATUS Status; 154 PIO_STACK_LOCATION IoStack; 155 156 // 157 // init event 158 // 159 KeInitializeEvent(&Event, NotificationEvent, FALSE); 160 161 // 162 // get device extension 163 // 164 CommonDeviceExtension = DeviceObject->DeviceExtension; 165 166 // 167 // set completion routine 168 // 169 IoSetCompletionRoutine(Irp, HidClassFDO_DispatchRequestSynchronousCompletion, &Event, TRUE, TRUE, TRUE); 170 171 ASSERT(Irp->CurrentLocation > 0); 172 // 173 // create stack location 174 // 175 IoSetNextIrpStackLocation(Irp); 176 177 // 178 // get next stack location 179 // 180 IoStack = IoGetCurrentIrpStackLocation(Irp); 181 182 // 183 // store device object 184 // 185 IoStack->DeviceObject = DeviceObject; 186 187 // 188 // sanity check 189 // 190 ASSERT(CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction] != NULL); 191 192 // 193 // call minidriver (hidusb) 194 // 195 Status = CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp); 196 197 // 198 // wait for the request to finish 199 // 200 if (Status == STATUS_PENDING) 201 { 202 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 203 204 // 205 // update status 206 // 207 Status = Irp->IoStatus.Status; 208 } 209 210 // 211 // done 212 // 213 return Status; 214 } 215 216 NTSTATUS 217 HidClassFDO_DispatchRequest( 218 IN PDEVICE_OBJECT DeviceObject, 219 IN PIRP Irp) 220 { 221 PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 222 NTSTATUS Status; 223 PIO_STACK_LOCATION IoStack; 224 225 // 226 // get device extension 227 // 228 CommonDeviceExtension = DeviceObject->DeviceExtension; 229 230 ASSERT(Irp->CurrentLocation > 0); 231 232 // 233 // create stack location 234 // 235 IoSetNextIrpStackLocation(Irp); 236 237 // 238 // get next stack location 239 // 240 IoStack = IoGetCurrentIrpStackLocation(Irp); 241 242 // 243 // store device object 244 // 245 IoStack->DeviceObject = DeviceObject; 246 247 // 248 // sanity check 249 // 250 ASSERT(CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction] != NULL); 251 252 // 253 // call driver 254 // 255 Status = CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp); 256 257 // 258 // done 259 // 260 return Status; 261 } 262 263 NTSTATUS 264 HidClassFDO_GetDescriptors( 265 IN PDEVICE_OBJECT DeviceObject) 266 { 267 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 268 PIRP Irp; 269 PIO_STACK_LOCATION IoStack; 270 NTSTATUS Status; 271 272 // 273 // get device extension 274 // 275 FDODeviceExtension = DeviceObject->DeviceExtension; 276 ASSERT(FDODeviceExtension->Common.IsFDO); 277 278 // 279 // let's allocate irp 280 // 281 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 282 if (!Irp) 283 { 284 // 285 // no memory 286 // 287 return STATUS_INSUFFICIENT_RESOURCES; 288 } 289 290 // 291 // get stack location 292 // 293 IoStack = IoGetNextIrpStackLocation(Irp); 294 295 // 296 // init stack location 297 // 298 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 299 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_DESCRIPTOR; 300 IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DESCRIPTOR); 301 IoStack->Parameters.DeviceIoControl.InputBufferLength = 0; 302 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL; 303 Irp->UserBuffer = &FDODeviceExtension->HidDescriptor; 304 305 // 306 // send request 307 // 308 Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); 309 if (!NT_SUCCESS(Status)) 310 { 311 // 312 // failed to get device descriptor 313 // 314 DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_DESCRIPTOR failed with %x\n", Status); 315 IoFreeIrp(Irp); 316 return Status; 317 } 318 319 // 320 // let's get device attributes 321 // 322 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_ATTRIBUTES; 323 IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DEVICE_ATTRIBUTES); 324 Irp->UserBuffer = &FDODeviceExtension->Common.Attributes; 325 326 // 327 // send request 328 // 329 Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); 330 if (!NT_SUCCESS(Status)) 331 { 332 // 333 // failed to get device descriptor 334 // 335 DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_ATTRIBUTES failed with %x\n", Status); 336 IoFreeIrp(Irp); 337 return Status; 338 } 339 340 // 341 // sanity checks 342 // 343 ASSERT(FDODeviceExtension->HidDescriptor.bLength == sizeof(HID_DESCRIPTOR)); 344 ASSERT(FDODeviceExtension->HidDescriptor.bNumDescriptors > 0); 345 ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength > 0); 346 ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].bReportType == HID_REPORT_DESCRIPTOR_TYPE); 347 348 // 349 // now allocate space for the report descriptor 350 // 351 FDODeviceExtension->ReportDescriptor = ExAllocatePoolWithTag(NonPagedPool, 352 FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength, 353 HIDCLASS_TAG); 354 if (!FDODeviceExtension->ReportDescriptor) 355 { 356 // 357 // not enough memory 358 // 359 IoFreeIrp(Irp); 360 return STATUS_INSUFFICIENT_RESOURCES; 361 } 362 363 // 364 // init stack location 365 // 366 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_REPORT_DESCRIPTOR; 367 IoStack->Parameters.DeviceIoControl.OutputBufferLength = FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength; 368 Irp->UserBuffer = FDODeviceExtension->ReportDescriptor; 369 370 // 371 // send request 372 // 373 Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); 374 if (!NT_SUCCESS(Status)) 375 { 376 // 377 // failed to get device descriptor 378 // 379 DPRINT1("[HIDCLASS] IOCTL_HID_GET_REPORT_DESCRIPTOR failed with %x\n", Status); 380 IoFreeIrp(Irp); 381 return Status; 382 } 383 384 // 385 // completed successfully 386 // 387 IoFreeIrp(Irp); 388 return STATUS_SUCCESS; 389 } 390 391 392 NTSTATUS 393 HidClassFDO_StartDevice( 394 IN PDEVICE_OBJECT DeviceObject, 395 IN PIRP Irp) 396 { 397 NTSTATUS Status; 398 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 399 400 // 401 // get device extension 402 // 403 FDODeviceExtension = DeviceObject->DeviceExtension; 404 ASSERT(FDODeviceExtension->Common.IsFDO); 405 406 // 407 // query capabilities 408 // 409 Status = HidClassFDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities); 410 if (!NT_SUCCESS(Status)) 411 { 412 DPRINT1("[HIDCLASS] Failed to retrieve capabilities %x\n", Status); 413 Irp->IoStatus.Status = Status; 414 IoCompleteRequest(Irp, IO_NO_INCREMENT); 415 return Status; 416 } 417 418 // 419 // let's start the lower device too 420 // 421 IoSkipCurrentIrpStackLocation(Irp); 422 Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); 423 if (!NT_SUCCESS(Status)) 424 { 425 DPRINT1("[HIDCLASS] Failed to start lower device with %x\n", Status); 426 Irp->IoStatus.Status = Status; 427 IoCompleteRequest(Irp, IO_NO_INCREMENT); 428 return Status; 429 } 430 431 // 432 // let's get the descriptors 433 // 434 Status = HidClassFDO_GetDescriptors(DeviceObject); 435 if (!NT_SUCCESS(Status)) 436 { 437 DPRINT1("[HIDCLASS] Failed to retrieve the descriptors %x\n", Status); 438 Irp->IoStatus.Status = Status; 439 IoCompleteRequest(Irp, IO_NO_INCREMENT); 440 return Status; 441 } 442 443 // 444 // now get the the collection description 445 // 446 Status = HidP_GetCollectionDescription(FDODeviceExtension->ReportDescriptor, FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength, NonPagedPool, &FDODeviceExtension->Common.DeviceDescription); 447 if (!NT_SUCCESS(Status)) 448 { 449 DPRINT1("[HIDCLASS] Failed to retrieve the collection description %x\n", Status); 450 Irp->IoStatus.Status = Status; 451 IoCompleteRequest(Irp, IO_NO_INCREMENT); 452 return Status; 453 } 454 455 // 456 // complete request 457 // 458 Irp->IoStatus.Status = Status; 459 IoCompleteRequest(Irp, IO_NO_INCREMENT); 460 return Status; 461 } 462 463 NTSTATUS 464 HidClassFDO_RemoveDevice( 465 IN PDEVICE_OBJECT DeviceObject, 466 IN PIRP Irp) 467 { 468 NTSTATUS Status; 469 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 470 471 // 472 // get device extension 473 // 474 FDODeviceExtension = DeviceObject->DeviceExtension; 475 ASSERT(FDODeviceExtension->Common.IsFDO); 476 477 /* FIXME cleanup */ 478 479 // 480 // dispatch to minidriver 481 // 482 IoSkipCurrentIrpStackLocation(Irp); 483 Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); 484 485 // 486 // complete request 487 // 488 Irp->IoStatus.Status = Status; 489 IoCompleteRequest(Irp, IO_NO_INCREMENT); 490 491 // 492 // detach and delete device 493 // 494 IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); 495 IoDeleteDevice(DeviceObject); 496 497 return Status; 498 } 499 500 NTSTATUS 501 HidClassFDO_CopyDeviceRelations( 502 IN PDEVICE_OBJECT DeviceObject, 503 OUT PDEVICE_RELATIONS *OutRelations) 504 { 505 PDEVICE_RELATIONS DeviceRelations; 506 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 507 ULONG Index; 508 509 // 510 // get device extension 511 // 512 FDODeviceExtension = DeviceObject->DeviceExtension; 513 ASSERT(FDODeviceExtension->Common.IsFDO); 514 515 // 516 // allocate result 517 // 518 DeviceRelations = ExAllocatePoolWithTag(NonPagedPool, 519 sizeof(DEVICE_RELATIONS) + (FDODeviceExtension->DeviceRelations->Count - 1) * sizeof(PDEVICE_OBJECT), 520 HIDCLASS_TAG); 521 if (!DeviceRelations) 522 { 523 // 524 // no memory 525 // 526 *OutRelations = NULL; 527 return STATUS_INSUFFICIENT_RESOURCES; 528 } 529 530 // 531 // copy device objects 532 // 533 for (Index = 0; Index < FDODeviceExtension->DeviceRelations->Count; Index++) 534 { 535 // 536 // reference pdo 537 // 538 ObReferenceObject(FDODeviceExtension->DeviceRelations->Objects[Index]); 539 540 // 541 // store object 542 // 543 DeviceRelations->Objects[Index] = FDODeviceExtension->DeviceRelations->Objects[Index]; 544 } 545 546 // 547 // set object count 548 // 549 DeviceRelations->Count = FDODeviceExtension->DeviceRelations->Count; 550 551 // 552 // store result 553 // 554 *OutRelations = DeviceRelations; 555 return STATUS_SUCCESS; 556 } 557 558 NTSTATUS 559 HidClassFDO_DeviceRelations( 560 IN PDEVICE_OBJECT DeviceObject, 561 IN PIRP Irp) 562 { 563 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 564 PIO_STACK_LOCATION IoStack; 565 NTSTATUS Status; 566 PDEVICE_RELATIONS DeviceRelations; 567 568 // 569 // get device extension 570 // 571 FDODeviceExtension = DeviceObject->DeviceExtension; 572 ASSERT(FDODeviceExtension->Common.IsFDO); 573 574 // 575 // get current irp stack location 576 // 577 IoStack = IoGetCurrentIrpStackLocation(Irp); 578 579 // 580 // check relations type 581 // 582 if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations) 583 { 584 // 585 // only bus relations are handled 586 // 587 IoSkipCurrentIrpStackLocation(Irp); 588 return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); 589 } 590 591 if (FDODeviceExtension->DeviceRelations == NULL) 592 { 593 // 594 // time to create the pdos 595 // 596 Status = HidClassPDO_CreatePDO(DeviceObject, &FDODeviceExtension->DeviceRelations); 597 if (!NT_SUCCESS(Status)) 598 { 599 // 600 // failed 601 // 602 DPRINT1("[HIDCLASS] HidClassPDO_CreatePDO failed with %x\n", Status); 603 Irp->IoStatus.Status = Status; 604 IoCompleteRequest(Irp, IO_NO_INCREMENT); 605 return STATUS_SUCCESS; 606 } 607 // 608 // sanity check 609 // 610 ASSERT(FDODeviceExtension->DeviceRelations->Count > 0); 611 } 612 613 // 614 // now copy device relations 615 // 616 Status = HidClassFDO_CopyDeviceRelations(DeviceObject, &DeviceRelations); 617 // 618 // store result 619 // 620 Irp->IoStatus.Status = Status; 621 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 622 623 // 624 // complete request 625 // 626 IoCompleteRequest(Irp, IO_NO_INCREMENT); 627 return Status; 628 } 629 630 NTSTATUS 631 HidClassFDO_PnP( 632 IN PDEVICE_OBJECT DeviceObject, 633 IN PIRP Irp) 634 { 635 PIO_STACK_LOCATION IoStack; 636 PHIDCLASS_FDO_EXTENSION FDODeviceExtension; 637 NTSTATUS Status; 638 639 // 640 // get device extension 641 // 642 FDODeviceExtension = DeviceObject->DeviceExtension; 643 ASSERT(FDODeviceExtension->Common.IsFDO); 644 645 // 646 // get current irp stack location 647 // 648 IoStack = IoGetCurrentIrpStackLocation(Irp); 649 switch (IoStack->MinorFunction) 650 { 651 case IRP_MN_START_DEVICE: 652 { 653 return HidClassFDO_StartDevice(DeviceObject, Irp); 654 } 655 case IRP_MN_REMOVE_DEVICE: 656 { 657 return HidClassFDO_RemoveDevice(DeviceObject, Irp); 658 } 659 case IRP_MN_QUERY_DEVICE_RELATIONS: 660 { 661 return HidClassFDO_DeviceRelations(DeviceObject, Irp); 662 } 663 case IRP_MN_QUERY_REMOVE_DEVICE: 664 case IRP_MN_QUERY_STOP_DEVICE: 665 case IRP_MN_CANCEL_REMOVE_DEVICE: 666 case IRP_MN_CANCEL_STOP_DEVICE: 667 { 668 // 669 // set status to success and fall through 670 // 671 Irp->IoStatus.Status = STATUS_SUCCESS; 672 } 673 default: 674 { 675 // 676 // dispatch to mini driver 677 // 678 IoCopyCurrentIrpStackLocationToNext(Irp); 679 Status = HidClassFDO_DispatchRequest(DeviceObject, Irp); 680 return Status; 681 } 682 } 683 } 684