1 /* 2 * PROJECT: ReactOS USB Port Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBPort plug and play functions 5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbport.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_USBPORT_CORE 14 #include "usbdebug.h" 15 16 IO_COMPLETION_ROUTINE USBPORT_FdoStartCompletion; 17 18 NTSTATUS 19 NTAPI 20 USBPORT_FdoStartCompletion(IN PDEVICE_OBJECT DeviceObject, 21 IN PIRP Irp, 22 IN PVOID Context) 23 { 24 KeSetEvent((PKEVENT)Context, EVENT_INCREMENT, FALSE); 25 return STATUS_MORE_PROCESSING_REQUIRED; 26 } 27 28 NTSTATUS 29 NTAPI 30 USBPORT_RegisterDeviceInterface(IN PDEVICE_OBJECT PdoDevice, 31 IN PDEVICE_OBJECT DeviceObject, 32 IN CONST GUID *InterfaceClassGuid, 33 IN BOOLEAN Enable) 34 { 35 PUSBPORT_RHDEVICE_EXTENSION DeviceExtension; 36 PUNICODE_STRING SymbolicLinkName; 37 NTSTATUS Status; 38 39 DPRINT("USBPORT_RegisterDeviceInterface: Enable - %x\n", Enable); 40 41 DeviceExtension = DeviceObject->DeviceExtension; 42 SymbolicLinkName = &DeviceExtension->CommonExtension.SymbolicLinkName; 43 44 if (Enable) 45 { 46 Status = IoRegisterDeviceInterface(PdoDevice, 47 InterfaceClassGuid, 48 NULL, 49 SymbolicLinkName); 50 51 if (NT_SUCCESS(Status)) 52 { 53 DeviceExtension->CommonExtension.IsInterfaceEnabled = 1; 54 55 Status = USBPORT_SetRegistryKeyValue(PdoDevice, 56 FALSE, 57 REG_SZ, 58 L"SymbolicName", 59 SymbolicLinkName->Buffer, 60 SymbolicLinkName->Length); 61 62 if (NT_SUCCESS(Status)) 63 { 64 DPRINT("USBPORT_RegisterDeviceInterface: LinkName - %wZ\n", 65 &DeviceExtension->CommonExtension.SymbolicLinkName); 66 67 Status = IoSetDeviceInterfaceState(SymbolicLinkName, TRUE); 68 } 69 } 70 } 71 else 72 { 73 /* Disable device interface */ 74 Status = IoSetDeviceInterfaceState(SymbolicLinkName, FALSE); 75 76 if (NT_SUCCESS(Status)) 77 { 78 RtlFreeUnicodeString(SymbolicLinkName); 79 DeviceExtension->CommonExtension.IsInterfaceEnabled = 0; // Disabled interface 80 } 81 } 82 83 return Status; 84 } 85 86 BOOLEAN 87 NTAPI 88 USBPORT_IsSelectiveSuspendEnabled(IN PDEVICE_OBJECT FdoDevice) 89 { 90 PUSBPORT_DEVICE_EXTENSION FdoExtension; 91 ULONG Disabled = 0; 92 93 DPRINT("USBPORT_IsSelectiveSuspendEnabled: ... \n"); 94 95 FdoExtension = FdoDevice->DeviceExtension; 96 97 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice, 98 FdoExtension->CommonExtension.LowerPdoDevice, 99 TRUE, 100 L"HcDisableSelectiveSuspend", 101 sizeof(L"HcDisableSelectiveSuspend"), 102 &Disabled, 103 sizeof(Disabled)); 104 105 return (Disabled == 0); 106 } 107 108 NTSTATUS 109 NTAPI 110 USBPORT_GetConfigValue(IN PWSTR ValueName, 111 IN ULONG ValueType, 112 IN PVOID ValueData, 113 IN ULONG ValueLength, 114 IN PVOID Context, 115 IN PVOID EntryContext) 116 { 117 NTSTATUS Status = STATUS_SUCCESS; 118 119 DPRINT("USBPORT_GetConfigValue \n"); 120 121 if (ValueType == REG_DWORD) 122 { 123 *(PULONG)EntryContext = *(PULONG)ValueData; 124 } 125 else 126 { 127 Status = STATUS_INVALID_PARAMETER; 128 } 129 130 return Status; 131 } 132 133 NTSTATUS 134 NTAPI 135 USBPORT_GetDefaultBIOSx(IN PDEVICE_OBJECT FdoDevice, 136 IN PULONG UsbBIOSx, 137 IN PULONG DisableSelectiveSuspend, 138 IN PULONG DisableCcDetect, 139 IN PULONG IdleEpSupport, 140 IN PULONG IdleEpSupportEx, 141 IN PULONG SoftRetry) 142 { 143 RTL_QUERY_REGISTRY_TABLE QueryTable[7]; 144 145 DPRINT("USBPORT_GetDefaultBIOS_X: ... \n"); 146 147 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 148 149 *UsbBIOSx = 2; 150 151 QueryTable[0].QueryRoutine = USBPORT_GetConfigValue; 152 QueryTable[0].Flags = 0; 153 QueryTable[0].Name = L"UsbBIOSx"; 154 QueryTable[0].EntryContext = UsbBIOSx; 155 QueryTable[0].DefaultType = REG_DWORD; 156 QueryTable[0].DefaultData = UsbBIOSx; 157 QueryTable[0].DefaultLength = sizeof(ULONG); 158 159 QueryTable[1].QueryRoutine = USBPORT_GetConfigValue; 160 QueryTable[1].Flags = 0; 161 QueryTable[1].Name = L"DisableSelectiveSuspend"; 162 QueryTable[1].EntryContext = DisableSelectiveSuspend; 163 QueryTable[1].DefaultType = REG_DWORD; 164 QueryTable[1].DefaultData = DisableSelectiveSuspend; 165 QueryTable[1].DefaultLength = sizeof(ULONG); 166 167 QueryTable[2].QueryRoutine = USBPORT_GetConfigValue; 168 QueryTable[2].Flags = 0; 169 QueryTable[2].Name = L"DisableCcDetect"; 170 QueryTable[2].EntryContext = DisableCcDetect; 171 QueryTable[2].DefaultType = REG_DWORD; 172 QueryTable[2].DefaultData = DisableCcDetect; 173 QueryTable[2].DefaultLength = sizeof(ULONG); 174 175 QueryTable[3].QueryRoutine = USBPORT_GetConfigValue; 176 QueryTable[3].Flags = 0; 177 QueryTable[3].Name = L"EnIdleEndpointSupport"; 178 QueryTable[3].EntryContext = IdleEpSupport; 179 QueryTable[3].DefaultType = REG_DWORD; 180 QueryTable[3].DefaultData = IdleEpSupport; 181 QueryTable[3].DefaultLength = sizeof(ULONG); 182 183 QueryTable[4].QueryRoutine = USBPORT_GetConfigValue; 184 QueryTable[4].Flags = 0; 185 QueryTable[4].Name = L"EnIdleEndpointSupportEx"; 186 QueryTable[4].EntryContext = IdleEpSupportEx; 187 QueryTable[4].DefaultType = REG_DWORD; 188 QueryTable[4].DefaultData = IdleEpSupportEx; 189 QueryTable[4].DefaultLength = sizeof(ULONG); 190 191 QueryTable[5].QueryRoutine = USBPORT_GetConfigValue; 192 QueryTable[5].Flags = 0; 193 QueryTable[5].Name = L"EnSoftRetry"; 194 QueryTable[5].EntryContext = SoftRetry; 195 QueryTable[5].DefaultType = REG_DWORD; 196 QueryTable[5].DefaultData = SoftRetry; 197 QueryTable[5].DefaultLength = sizeof(ULONG); 198 199 return RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, 200 L"usb", 201 QueryTable, 202 NULL, 203 NULL); 204 } 205 206 NTSTATUS 207 NTAPI 208 USBPORT_IsCompanionController(IN PDEVICE_OBJECT DeviceObject, 209 IN BOOLEAN *IsCompanion) 210 { 211 PDEVICE_OBJECT HighestDevice; 212 PIRP Irp; 213 KEVENT Event; 214 PIO_STACK_LOCATION IoStack; 215 PCI_DEVICE_PRESENT_INTERFACE PciInterface = {0}; 216 PCI_DEVICE_PRESENCE_PARAMETERS Parameters = {0}; 217 IO_STATUS_BLOCK IoStatusBlock; 218 NTSTATUS Status; 219 BOOLEAN IsPresent; 220 221 DPRINT("USBPORT_IsCompanionController: ... \n"); 222 223 *IsCompanion = FALSE; 224 225 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 226 227 HighestDevice = IoGetAttachedDeviceReference(DeviceObject); 228 229 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, 230 HighestDevice, 231 NULL, 232 0, 233 NULL, 234 &Event, 235 &IoStatusBlock); 236 237 if (!Irp) 238 { 239 Status = STATUS_INSUFFICIENT_RESOURCES; 240 ObDereferenceObject(HighestDevice); 241 return Status; 242 } 243 244 IoStack = IoGetNextIrpStackLocation(Irp); 245 246 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 247 Irp->IoStatus.Information = 0; 248 249 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE; 250 251 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE; 252 IoStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE); 253 IoStack->Parameters.QueryInterface.Version = 1; 254 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)&PciInterface; 255 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0; 256 257 Status = IoCallDriver(HighestDevice, Irp); 258 259 if (Status == STATUS_PENDING) 260 { 261 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 262 Status = IoStatusBlock.Status; 263 } 264 265 if (!NT_SUCCESS(Status)) 266 { 267 DPRINT1("USBPORT_IsCompanionController: query interface failed\\n"); 268 ObDereferenceObject(HighestDevice); 269 return Status; 270 } 271 272 DPRINT("USBPORT_IsCompanionController: query interface succeeded\n"); 273 274 if (PciInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE)) 275 { 276 DPRINT1("USBPORT_IsCompanionController: old version\n"); 277 ObDereferenceObject(HighestDevice); 278 return Status; 279 } 280 281 Parameters.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE); 282 283 Parameters.BaseClass = PCI_CLASS_SERIAL_BUS_CTLR; 284 Parameters.SubClass = PCI_SUBCLASS_SB_USB; 285 Parameters.ProgIf = PCI_INTERFACE_USB_ID_EHCI; 286 287 Parameters.Flags = PCI_USE_LOCAL_BUS | 288 PCI_USE_LOCAL_DEVICE | 289 PCI_USE_CLASS_SUBCLASS | 290 PCI_USE_PROGIF; 291 292 IsPresent = (PciInterface.IsDevicePresentEx)(PciInterface.Context, 293 &Parameters); 294 295 if (IsPresent) 296 { 297 DPRINT("USBPORT_IsCompanionController: Present EHCI controller for FDO - %p\n", 298 DeviceObject); 299 } 300 else 301 { 302 DPRINT("USBPORT_IsCompanionController: No EHCI controller for FDO - %p\n", 303 DeviceObject); 304 } 305 306 *IsCompanion = IsPresent; 307 308 (PciInterface.InterfaceDereference)(PciInterface.Context); 309 310 ObDereferenceObject(HighestDevice); 311 312 return Status; 313 } 314 315 NTSTATUS 316 NTAPI 317 USBPORT_QueryPciBusInterface(IN PDEVICE_OBJECT FdoDevice) 318 { 319 PUSBPORT_DEVICE_EXTENSION FdoExtension; 320 PBUS_INTERFACE_STANDARD BusInterface; 321 PIO_STACK_LOCATION IoStack; 322 IO_STATUS_BLOCK IoStatusBlock; 323 PDEVICE_OBJECT HighestDevice; 324 KEVENT Event; 325 PIRP Irp; 326 NTSTATUS Status; 327 328 DPRINT("USBPORT_QueryPciBusInterface: ... \n"); 329 330 FdoExtension = FdoDevice->DeviceExtension; 331 BusInterface = &FdoExtension->BusInterface; 332 333 RtlZeroMemory(BusInterface, sizeof(BUS_INTERFACE_STANDARD)); 334 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 335 HighestDevice = IoGetAttachedDeviceReference(FdoDevice); 336 337 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, 338 HighestDevice, 339 NULL, 340 0, 341 NULL, 342 &Event, 343 &IoStatusBlock); 344 345 if (Irp) 346 { 347 IoStack = IoGetNextIrpStackLocation(Irp); 348 349 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 350 Irp->IoStatus.Information = 0; 351 352 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE; 353 354 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD; 355 IoStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD); 356 IoStack->Parameters.QueryInterface.Version = 1; 357 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface; 358 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0; 359 360 Status = IoCallDriver(HighestDevice, Irp); 361 362 if (Status == STATUS_PENDING) 363 { 364 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 365 Status = IoStatusBlock.Status; 366 } 367 } 368 else 369 { 370 Status = STATUS_INSUFFICIENT_RESOURCES; 371 } 372 373 ObDereferenceObject(HighestDevice); 374 375 DPRINT("USBPORT_QueryPciBusInterface: return Status - %x\n", Status); 376 377 return Status; 378 } 379 380 NTSTATUS 381 NTAPI 382 USBPORT_QueryCapabilities(IN PDEVICE_OBJECT FdoDevice, 383 IN PDEVICE_CAPABILITIES Capabilities) 384 { 385 PUSBPORT_DEVICE_EXTENSION FdoExtention; 386 PIRP Irp; 387 NTSTATUS Status; 388 PIO_STACK_LOCATION IoStack; 389 KEVENT Event; 390 391 DPRINT("USBPORT_QueryCapabilities: ... \n"); 392 393 FdoExtention = FdoDevice->DeviceExtension; 394 395 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); 396 397 Capabilities->Size = sizeof(DEVICE_CAPABILITIES); 398 Capabilities->Version = 1; 399 Capabilities->Address = MAXULONG; 400 Capabilities->UINumber = MAXULONG; 401 402 Irp = IoAllocateIrp(FdoExtention->CommonExtension.LowerDevice->StackSize, 403 FALSE); 404 405 if (!Irp) 406 { 407 DPRINT1("USBPORT_QueryCapabilities: No resources - IoAllocateIrp!\n"); 408 return STATUS_INSUFFICIENT_RESOURCES; 409 } 410 411 IoStack = IoGetCurrentIrpStackLocation(Irp); 412 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 413 414 IoStack = IoGetNextIrpStackLocation(Irp); 415 IoStack->MajorFunction = IRP_MJ_PNP; 416 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES; 417 418 KeInitializeEvent(&Event, NotificationEvent, FALSE); 419 420 IoSetCompletionRoutine(Irp, 421 USBPORT_FdoStartCompletion, 422 &Event, 423 TRUE, 424 TRUE, 425 TRUE); 426 427 IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities; 428 429 Status = IoCallDriver(FdoExtention->CommonExtension.LowerDevice, Irp); 430 431 if (Status == STATUS_PENDING) 432 { 433 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 434 Status = Irp->IoStatus.Status; 435 } 436 437 if (NT_SUCCESS(Status) && Capabilities) 438 { 439 USBPORT_DumpingCapabilities(Capabilities); 440 } 441 442 IoFreeIrp(Irp); 443 444 return Status; 445 } 446 447 NTSTATUS 448 NTAPI 449 USBPORT_CreateLegacySymbolicLink(IN PDEVICE_OBJECT FdoDevice) 450 { 451 PUSBPORT_DEVICE_EXTENSION FdoExtension; 452 WCHAR CharName[255] = {0}; 453 WCHAR CharDosName[255] = {0}; 454 UNICODE_STRING DeviceName; 455 NTSTATUS Status; 456 457 FdoExtension = FdoDevice->DeviceExtension; 458 459 RtlStringCbPrintfW(CharName, 460 sizeof(CharName), 461 L"\\Device\\USBFDO-%d", 462 FdoExtension->FdoNameNumber); 463 464 RtlInitUnicodeString(&DeviceName, CharName); 465 466 RtlStringCbPrintfW(CharDosName, 467 sizeof(CharDosName), 468 L"\\DosDevices\\HCD%d", 469 FdoExtension->FdoNameNumber); 470 471 RtlInitUnicodeString(&FdoExtension->DosDeviceSymbolicName, CharDosName); 472 473 DPRINT("USBPORT_CreateLegacySymbolicLink: DeviceName - %wZ, DosSymbolicName - %wZ\n", 474 &DeviceName, 475 &FdoExtension->DosDeviceSymbolicName); 476 477 Status = IoCreateSymbolicLink(&FdoExtension->DosDeviceSymbolicName, 478 &DeviceName); 479 480 if (NT_SUCCESS(Status)) 481 { 482 FdoExtension->Flags |= USBPORT_FLAG_DOS_SYMBOLIC_NAME; 483 } 484 485 return Status; 486 } 487 488 NTSTATUS 489 NTAPI 490 USBPORT_StopDevice(IN PDEVICE_OBJECT FdoDevice) 491 { 492 DPRINT1("USBPORT_StopDevice: UNIMPLEMENTED. FIXME\n"); 493 DbgBreakPoint(); 494 return STATUS_SUCCESS; 495 } 496 497 NTSTATUS 498 NTAPI 499 USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice, 500 IN PUSBPORT_RESOURCES UsbPortResources) 501 { 502 PUSBPORT_DEVICE_EXTENSION FdoExtension; 503 PUSBPORT_REGISTRATION_PACKET Packet; 504 NTSTATUS Status; 505 PCI_COMMON_CONFIG PciConfig; 506 ULONG BytesRead; 507 DEVICE_DESCRIPTION DeviceDescription; 508 PDMA_ADAPTER DmaAdapter = NULL; 509 ULONG MiniPortStatus; 510 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer; 511 ULONG ResultLength; 512 ULONG DisableSelectiveSuspend = 0; 513 ULONG DisableCcDetect = 0; 514 ULONG IdleEpSupport = 0; 515 ULONG IdleEpSupportEx = 0; 516 ULONG SoftRetry = 0; 517 ULONG Limit2GB = 0; 518 ULONG TotalBusBandwidth = 0; 519 BOOLEAN IsCompanion = FALSE; 520 ULONG LegacyBIOS; 521 ULONG MiniportFlags; 522 ULONG ix; 523 524 DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n", 525 FdoDevice, 526 UsbPortResources); 527 528 FdoExtension = FdoDevice->DeviceExtension; 529 Packet = &FdoExtension->MiniPortInterface->Packet; 530 531 Status = USBPORT_QueryPciBusInterface(FdoDevice); 532 if (!NT_SUCCESS(Status)) 533 goto ExitWithError; 534 535 BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context, 536 PCI_WHICHSPACE_CONFIG, 537 &PciConfig, 538 0, 539 PCI_COMMON_HDR_LENGTH); 540 541 if (BytesRead != PCI_COMMON_HDR_LENGTH) 542 { 543 DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n"); 544 goto ExitWithError; 545 } 546 547 FdoExtension->VendorID = PciConfig.VendorID; 548 FdoExtension->DeviceID = PciConfig.DeviceID; 549 FdoExtension->RevisionID = PciConfig.RevisionID; 550 FdoExtension->ProgIf = PciConfig.ProgIf; 551 FdoExtension->SubClass = PciConfig.SubClass; 552 FdoExtension->BaseClass = PciConfig.BaseClass; 553 554 RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription)); 555 556 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; 557 DeviceDescription.Master = TRUE; 558 DeviceDescription.ScatterGather = TRUE; 559 DeviceDescription.Dma32BitAddresses = TRUE; 560 DeviceDescription.InterfaceType = PCIBus; 561 DeviceDescription.DmaWidth = Width32Bits; 562 DeviceDescription.DmaSpeed = Compatible; 563 DeviceDescription.MaximumLength = MAXULONG; 564 565 DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice, 566 &DeviceDescription, 567 &FdoExtension->NumberMapRegs); 568 569 FdoExtension->DmaAdapter = DmaAdapter; 570 571 if (!DmaAdapter) 572 { 573 DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n"); 574 Status = STATUS_INSUFFICIENT_RESOURCES; 575 goto ExitWithError; 576 } 577 578 Status = USBPORT_CreateWorkerThread(FdoDevice); 579 if (!NT_SUCCESS(Status)) 580 goto ExitWithError; 581 582 Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities); 583 if (!NT_SUCCESS(Status)) 584 goto ExitWithError; 585 586 FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16; 587 FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF; 588 589 Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice, 590 DevicePropertyBusNumber, 591 sizeof(ULONG), 592 &FdoExtension->BusNumber, 593 &ResultLength); 594 595 if (!NT_SUCCESS(Status)) 596 goto ExitWithError; 597 598 KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock); 599 KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock); 600 KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock); 601 KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock); 602 KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock); 603 KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock); 604 KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock); 605 KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock); 606 KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock); 607 KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock); 608 KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock); 609 KeInitializeSpinLock(&FdoExtension->MiniportSpinLock); 610 KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock); 611 KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock); 612 KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock); 613 KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock); 614 KeInitializeSpinLock(&FdoExtension->TtSpinLock); 615 616 KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice); 617 618 KeInitializeDpc(&FdoExtension->TransferFlushDpc, 619 USBPORT_TransferFlushDpc, 620 FdoDevice); 621 622 KeInitializeDpc(&FdoExtension->WorkerRequestDpc, 623 USBPORT_WorkerRequestDpc, 624 FdoDevice); 625 626 KeInitializeDpc(&FdoExtension->HcWakeDpc, 627 USBPORT_HcWakeDpc, 628 FdoDevice); 629 630 IoCsqInitialize(&FdoExtension->IdleIoCsq, 631 USBPORT_InsertIdleIrp, 632 USBPORT_RemoveIdleIrp, 633 USBPORT_PeekNextIdleIrp, 634 USBPORT_AcquireIdleLock, 635 USBPORT_ReleaseIdleLock, 636 USBPORT_CompleteCanceledIdleIrp); 637 638 IoCsqInitialize(&FdoExtension->BadRequestIoCsq, 639 USBPORT_InsertBadRequest, 640 USBPORT_RemoveBadRequest, 641 USBPORT_PeekNextBadRequest, 642 USBPORT_AcquireBadRequestLock, 643 USBPORT_ReleaseBadRequestLock, 644 USBPORT_CompleteCanceledBadRequest); 645 646 FdoExtension->IsrDpcCounter = -1; 647 FdoExtension->IsrDpcHandlerCounter = -1; 648 FdoExtension->IdleLockCounter = -1; 649 FdoExtension->BadRequestLockCounter = -1; 650 FdoExtension->ChirpRootPortLock = -1; 651 652 FdoExtension->RHInitCallBackLock = 0; 653 654 FdoExtension->UsbAddressBitMap[0] = 1; 655 FdoExtension->UsbAddressBitMap[1] = 0; 656 FdoExtension->UsbAddressBitMap[2] = 0; 657 FdoExtension->UsbAddressBitMap[3] = 0; 658 659 USBPORT_GetDefaultBIOSx(FdoDevice, 660 &FdoExtension->UsbBIOSx, 661 &DisableSelectiveSuspend, 662 &DisableCcDetect, 663 &IdleEpSupport, 664 &IdleEpSupportEx, 665 &SoftRetry); 666 667 if (DisableSelectiveSuspend) 668 FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS; 669 670 if (!DisableSelectiveSuspend && 671 USBPORT_IsSelectiveSuspendEnabled(FdoDevice)) 672 { 673 FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND; 674 } 675 676 MiniportFlags = Packet->MiniPortFlags; 677 678 if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING) 679 FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING; 680 681 if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT) 682 FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT; 683 684 if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS) 685 FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) | 686 USBPORT_FLAG_BIOS_DISABLE_SS; 687 688 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice, 689 TRUE, 690 REG_DWORD, 691 L"EnIdleEndpointSupport", 692 &IdleEpSupport, 693 sizeof(IdleEpSupport)); 694 695 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice, 696 TRUE, 697 REG_DWORD, 698 L"EnIdleEndpointSupportEx", 699 &IdleEpSupportEx, 700 sizeof(IdleEpSupportEx)); 701 702 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice, 703 TRUE, 704 REG_DWORD, 705 L"EnSoftRetry", 706 &SoftRetry, 707 sizeof(SoftRetry)); 708 709 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice, 710 FdoExtension->CommonExtension.LowerPdoDevice, 711 TRUE, 712 L"CommonBuffer2GBLimit", 713 sizeof(L"CommonBuffer2GBLimit"), 714 &Limit2GB, 715 sizeof(Limit2GB)); 716 717 FdoExtension->CommonBufferLimit = (Limit2GB != 0); 718 719 if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR && 720 FdoExtension->SubClass == PCI_SUBCLASS_SB_USB && 721 FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI) 722 { 723 Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion); 724 725 if (!NT_SUCCESS(Status)) 726 { 727 if (IsCompanion) 728 { 729 FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC; 730 } 731 else 732 { 733 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC; 734 } 735 } 736 } 737 738 if (DisableCcDetect) 739 { 740 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC; 741 } 742 743 TotalBusBandwidth = Packet->MiniPortBusBandwidth; 744 FdoExtension->TotalBusBandwidth = TotalBusBandwidth; 745 746 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice, 747 FdoExtension->CommonExtension.LowerPdoDevice, 748 TRUE, 749 L"TotalBusBandwidth", 750 sizeof(L"TotalBusBandwidth"), 751 &TotalBusBandwidth, 752 sizeof(TotalBusBandwidth)); 753 754 if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth) 755 { 756 FdoExtension->TotalBusBandwidth = TotalBusBandwidth; 757 } 758 759 for (ix = 0; ix < USB2_FRAMES; ix++) 760 { 761 FdoExtension->Bandwidth[ix] = FdoExtension->TotalBusBandwidth - 762 FdoExtension->TotalBusBandwidth / 10; 763 } 764 765 FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool, 766 sizeof(USBPORT_IRP_TABLE), 767 USB_PORT_TAG); 768 769 if (!FdoExtension->ActiveIrpTable) 770 { 771 DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n"); 772 goto ExitWithError; 773 } 774 775 RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE)); 776 777 FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool, 778 sizeof(USBPORT_IRP_TABLE), 779 USB_PORT_TAG); 780 781 if (!FdoExtension->PendingIrpTable) 782 { 783 DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n"); 784 goto ExitWithError; 785 } 786 787 RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE)); 788 789 Status = IoConnectInterrupt(&FdoExtension->InterruptObject, 790 USBPORT_InterruptService, 791 (PVOID)FdoDevice, 792 0, 793 UsbPortResources->InterruptVector, 794 UsbPortResources->InterruptLevel, 795 UsbPortResources->InterruptLevel, 796 UsbPortResources->InterruptMode, 797 UsbPortResources->ShareVector, 798 UsbPortResources->InterruptAffinity, 799 0); 800 801 802 if (!NT_SUCCESS(Status)) 803 { 804 DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n"); 805 goto ExitWithError; 806 } 807 808 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED; 809 810 if (Packet->MiniPortExtensionSize) 811 { 812 RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize); 813 } 814 815 if (Packet->MiniPortResourcesSize) 816 { 817 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice, 818 Packet->MiniPortResourcesSize); 819 820 if (!HeaderBuffer) 821 { 822 DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n"); 823 Status = STATUS_INSUFFICIENT_RESOURCES; 824 goto ExitWithError; 825 } 826 827 UsbPortResources->StartVA = HeaderBuffer->VirtualAddress; 828 UsbPortResources->StartPA = HeaderBuffer->PhysicalAddress; 829 830 FdoExtension->MiniPortCommonBuffer = HeaderBuffer; 831 } 832 else 833 { 834 FdoExtension->MiniPortCommonBuffer = NULL; 835 } 836 837 MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt, 838 UsbPortResources); 839 840 if (UsbPortResources->LegacySupport) 841 { 842 FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT; 843 LegacyBIOS = 1; 844 } 845 else 846 { 847 LegacyBIOS = 0; 848 } 849 850 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice, 851 FALSE, 852 REG_DWORD, 853 L"DetectedLegacyBIOS", 854 &LegacyBIOS, 855 sizeof(LegacyBIOS)); 856 857 if (MiniPortStatus) 858 { 859 DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n", 860 MiniPortStatus); 861 862 if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED) 863 { 864 IoDisconnectInterrupt(FdoExtension->InterruptObject); 865 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED; 866 } 867 868 if (FdoExtension->MiniPortCommonBuffer) 869 { 870 USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer); 871 FdoExtension->MiniPortCommonBuffer = NULL; 872 } 873 874 goto ExitWithError; 875 } 876 else 877 { 878 FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED; 879 USBPORT_MiniportInterrupts(FdoDevice, TRUE); 880 } 881 882 FdoExtension->TimerValue = 500; 883 USBPORT_StartTimer((PVOID)FdoDevice, 500); 884 885 Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice, 886 FdoDevice, 887 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, 888 TRUE); 889 890 if (!NT_SUCCESS(Status)) 891 { 892 DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n"); 893 goto ExitWithError; 894 } 895 896 USBPORT_CreateLegacySymbolicLink(FdoDevice); 897 898 FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED; 899 900 DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status); 901 return Status; 902 903 ExitWithError: 904 USBPORT_StopDevice(FdoDevice); 905 906 DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status); 907 return Status; 908 } 909 910 NTSTATUS 911 NTAPI 912 USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice, 913 IN PIRP Irp, 914 IN PUSBPORT_RESOURCES UsbPortResources) 915 { 916 PCM_RESOURCE_LIST AllocatedResourcesTranslated; 917 PCM_PARTIAL_RESOURCE_LIST ResourceList; 918 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 919 PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL; 920 PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL; 921 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL; 922 PIO_STACK_LOCATION IoStack; 923 ULONG ix; 924 NTSTATUS Status = STATUS_SUCCESS; 925 926 DPRINT("USBPORT_ParseResources: ... \n"); 927 928 IoStack = IoGetCurrentIrpStackLocation(Irp); 929 AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated; 930 931 if (AllocatedResourcesTranslated) 932 { 933 RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES)); 934 935 ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList; 936 937 PartialDescriptor = &ResourceList->PartialDescriptors[0]; 938 939 for (ix = 0; ix < ResourceList->Count; ++ix) 940 { 941 if (PartialDescriptor->Type == CmResourceTypePort) 942 { 943 if (!PortDescriptor) 944 PortDescriptor = PartialDescriptor; 945 } 946 else if (PartialDescriptor->Type == CmResourceTypeInterrupt) 947 { 948 if (!InterruptDescriptor) 949 InterruptDescriptor = PartialDescriptor; 950 } 951 else if (PartialDescriptor->Type == CmResourceTypeMemory) 952 { 953 if (!MemoryDescriptor) 954 MemoryDescriptor = PartialDescriptor; 955 } 956 957 PartialDescriptor += 1; 958 } 959 960 if (PortDescriptor) 961 { 962 if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO) 963 { 964 UsbPortResources->ResourceBase = (PVOID)(ULONG_PTR)PortDescriptor->u.Port.Start.QuadPart; 965 } 966 else 967 { 968 UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start, 969 PortDescriptor->u.Port.Length, 970 0); 971 } 972 973 UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length; 974 975 if (UsbPortResources->ResourceBase) 976 { 977 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT; 978 } 979 else 980 { 981 Status = STATUS_NONE_MAPPED; 982 } 983 } 984 985 if (MemoryDescriptor && NT_SUCCESS(Status)) 986 { 987 UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length; 988 989 UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start, 990 MemoryDescriptor->u.Memory.Length, 991 0); 992 993 if (UsbPortResources->ResourceBase) 994 { 995 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY; 996 } 997 else 998 { 999 Status = STATUS_NONE_MAPPED; 1000 } 1001 } 1002 1003 if (InterruptDescriptor && NT_SUCCESS(Status)) 1004 { 1005 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT; 1006 1007 UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector; 1008 UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level; 1009 UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity; 1010 1011 UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition == 1012 CmResourceShareShared; 1013 1014 UsbPortResources->InterruptMode = InterruptDescriptor->Flags == 1015 CM_RESOURCE_INTERRUPT_LATCHED; 1016 } 1017 } 1018 else 1019 { 1020 Status = STATUS_NONE_MAPPED; 1021 } 1022 1023 return Status; 1024 } 1025 1026 NTSTATUS 1027 NTAPI 1028 USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice, 1029 OUT PDEVICE_OBJECT *RootHubPdo) 1030 { 1031 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1032 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 1033 UNICODE_STRING DeviceName; 1034 ULONG DeviceNumber = 0; 1035 PDEVICE_OBJECT DeviceObject = NULL; 1036 WCHAR CharDeviceName[64]; 1037 NTSTATUS Status = STATUS_SUCCESS; 1038 1039 DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n", 1040 FdoDevice, 1041 RootHubPdo); 1042 1043 FdoExtension = FdoDevice->DeviceExtension; 1044 1045 do 1046 { 1047 RtlStringCbPrintfW(CharDeviceName, 1048 sizeof(CharDeviceName), 1049 L"\\Device\\USBPDO-%d", 1050 DeviceNumber); 1051 1052 RtlInitUnicodeString(&DeviceName, CharDeviceName); 1053 1054 DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName); 1055 1056 Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject, 1057 sizeof(USBPORT_RHDEVICE_EXTENSION), 1058 &DeviceName, 1059 FILE_DEVICE_BUS_EXTENDER, 1060 0, 1061 FALSE, 1062 &DeviceObject); 1063 1064 ++DeviceNumber; 1065 } 1066 while (Status == STATUS_OBJECT_NAME_COLLISION); 1067 1068 if (!NT_SUCCESS(Status)) 1069 { 1070 *RootHubPdo = NULL; 1071 DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n"); 1072 return Status; 1073 } 1074 1075 if (DeviceObject) 1076 { 1077 PdoExtension = DeviceObject->DeviceExtension; 1078 1079 RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION)); 1080 1081 PdoExtension->CommonExtension.SelfDevice = DeviceObject; 1082 PdoExtension->CommonExtension.IsPDO = TRUE; 1083 1084 PdoExtension->FdoDevice = FdoDevice; 1085 PdoExtension->PdoNameNumber = DeviceNumber; 1086 1087 USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject); 1088 1089 DeviceObject->StackSize = FdoDevice->StackSize; 1090 1091 DeviceObject->Flags |= DO_POWER_PAGABLE; 1092 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1093 } 1094 else 1095 { 1096 Status = STATUS_UNSUCCESSFUL; 1097 } 1098 1099 if (!NT_SUCCESS(Status)) 1100 *RootHubPdo = NULL; 1101 else 1102 *RootHubPdo = DeviceObject; 1103 1104 DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject); 1105 return Status; 1106 } 1107 1108 NTSTATUS 1109 NTAPI 1110 USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice, 1111 IN PIRP Irp) 1112 { 1113 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1114 PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension; 1115 PUSBPORT_REGISTRATION_PACKET Packet; 1116 PUSBPORT_RESOURCES UsbPortResources; 1117 PIO_STACK_LOCATION IoStack; 1118 UCHAR Minor; 1119 KEVENT Event; 1120 NTSTATUS Status; 1121 DEVICE_RELATION_TYPE RelationType; 1122 PDEVICE_RELATIONS DeviceRelations; 1123 PDEVICE_OBJECT RootHubPdo; 1124 1125 FdoExtension = FdoDevice->DeviceExtension; 1126 FdoCommonExtension = &FdoExtension->CommonExtension; 1127 UsbPortResources = &FdoExtension->UsbPortResources; 1128 Packet = &FdoExtension->MiniPortInterface->Packet; 1129 1130 IoStack = IoGetCurrentIrpStackLocation(Irp); 1131 Minor = IoStack->MinorFunction; 1132 1133 DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor); 1134 1135 RelationType = IoStack->Parameters.QueryDeviceRelations.Type; 1136 1137 switch (Minor) 1138 { 1139 case IRP_MN_START_DEVICE: 1140 DPRINT("IRP_MN_START_DEVICE\n"); 1141 1142 KeInitializeEvent(&Event, NotificationEvent, FALSE); 1143 1144 IoCopyCurrentIrpStackLocationToNext(Irp); 1145 1146 IoSetCompletionRoutine(Irp, 1147 USBPORT_FdoStartCompletion, 1148 &Event, 1149 TRUE, 1150 TRUE, 1151 TRUE); 1152 1153 Status = IoCallDriver(FdoCommonExtension->LowerDevice, 1154 Irp); 1155 1156 if (Status == STATUS_PENDING) 1157 { 1158 KeWaitForSingleObject(&Event, 1159 Suspended, 1160 KernelMode, 1161 FALSE, 1162 NULL); 1163 1164 Status = Irp->IoStatus.Status; 1165 } 1166 1167 if (!NT_SUCCESS(Status)) 1168 { 1169 goto Exit; 1170 } 1171 1172 Status = USBPORT_ParseResources(FdoDevice, 1173 Irp, 1174 UsbPortResources); 1175 1176 if (!NT_SUCCESS(Status)) 1177 { 1178 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED; 1179 goto Exit; 1180 } 1181 1182 Status = USBPORT_StartDevice(FdoDevice, UsbPortResources); 1183 1184 if (!NT_SUCCESS(Status)) 1185 { 1186 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED; 1187 goto Exit; 1188 } 1189 1190 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT; 1191 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED; 1192 1193 FdoCommonExtension->DevicePowerState = PowerDeviceD0; 1194 1195 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 1196 { 1197 USBPORT_AddUSB2Fdo(FdoDevice); 1198 } 1199 else 1200 { 1201 USBPORT_AddUSB1Fdo(FdoDevice); 1202 } 1203 1204 Exit: 1205 Irp->IoStatus.Status = Status; 1206 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1207 return Status; 1208 1209 case IRP_MN_QUERY_REMOVE_DEVICE: 1210 DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n"); 1211 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 1212 { 1213 DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n"); 1214 } 1215 1216 Irp->IoStatus.Status = STATUS_SUCCESS; 1217 goto ForwardIrp; 1218 1219 case IRP_MN_REMOVE_DEVICE: 1220 DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n"); 1221 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED; 1222 1223 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED && 1224 !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT)) 1225 { 1226 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n"); 1227 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT; 1228 } 1229 1230 Irp->IoStatus.Status = STATUS_SUCCESS; 1231 IoSkipCurrentIrpStackLocation(Irp); 1232 Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp); 1233 1234 IoDetachDevice(FdoCommonExtension->LowerDevice); 1235 1236 RootHubPdo = FdoExtension->RootHubPdo; 1237 1238 IoDeleteDevice(FdoDevice); 1239 1240 if (RootHubPdo) 1241 { 1242 IoDeleteDevice(RootHubPdo); 1243 } 1244 1245 return Status; 1246 1247 case IRP_MN_CANCEL_REMOVE_DEVICE: 1248 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n"); 1249 Irp->IoStatus.Status = STATUS_SUCCESS; 1250 goto ForwardIrp; 1251 1252 case IRP_MN_STOP_DEVICE: 1253 DPRINT("IRP_MN_STOP_DEVICE\n"); 1254 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED) 1255 { 1256 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n"); 1257 1258 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED; 1259 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT; 1260 } 1261 1262 Irp->IoStatus.Status = STATUS_SUCCESS; 1263 goto ForwardIrp; 1264 1265 case IRP_MN_QUERY_STOP_DEVICE: 1266 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n"); 1267 Irp->IoStatus.Status = STATUS_SUCCESS; 1268 goto ForwardIrp; 1269 1270 case IRP_MN_CANCEL_STOP_DEVICE: 1271 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n"); 1272 Irp->IoStatus.Status = STATUS_SUCCESS; 1273 goto ForwardIrp; 1274 1275 case IRP_MN_QUERY_DEVICE_RELATIONS: 1276 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n"); 1277 if (RelationType == BusRelations) 1278 { 1279 DeviceRelations = ExAllocatePoolWithTag(PagedPool, 1280 sizeof(DEVICE_RELATIONS), 1281 USB_PORT_TAG); 1282 1283 if (!DeviceRelations) 1284 { 1285 Status = STATUS_INSUFFICIENT_RESOURCES; 1286 Irp->IoStatus.Status = Status; 1287 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1288 return Status; 1289 } 1290 1291 DeviceRelations->Count = 0; 1292 DeviceRelations->Objects[0] = NULL; 1293 1294 if (!FdoExtension->RootHubPdo) 1295 { 1296 Status = USBPORT_CreatePdo(FdoDevice, 1297 &FdoExtension->RootHubPdo); 1298 1299 if (!NT_SUCCESS(Status)) 1300 { 1301 ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG); 1302 goto ForwardIrp; 1303 } 1304 } 1305 else 1306 { 1307 Status = STATUS_SUCCESS; 1308 } 1309 1310 DeviceRelations->Count = 1; 1311 DeviceRelations->Objects[0] = FdoExtension->RootHubPdo; 1312 1313 ObReferenceObject(FdoExtension->RootHubPdo); 1314 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1315 } 1316 else 1317 { 1318 if (RelationType == RemovalRelations) 1319 { 1320 DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n"); 1321 } 1322 1323 goto ForwardIrp; 1324 } 1325 1326 Irp->IoStatus.Status = Status; 1327 goto ForwardIrp; 1328 1329 case IRP_MN_QUERY_INTERFACE: 1330 DPRINT("IRP_MN_QUERY_INTERFACE\n"); 1331 goto ForwardIrp; 1332 1333 case IRP_MN_QUERY_CAPABILITIES: 1334 DPRINT("IRP_MN_QUERY_CAPABILITIES\n"); 1335 goto ForwardIrp; 1336 1337 case IRP_MN_QUERY_RESOURCES: 1338 DPRINT("IRP_MN_QUERY_RESOURCES\n"); 1339 goto ForwardIrp; 1340 1341 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 1342 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 1343 goto ForwardIrp; 1344 1345 case IRP_MN_QUERY_DEVICE_TEXT: 1346 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n"); 1347 goto ForwardIrp; 1348 1349 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 1350 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 1351 goto ForwardIrp; 1352 1353 case IRP_MN_READ_CONFIG: 1354 DPRINT("IRP_MN_READ_CONFIG\n"); 1355 goto ForwardIrp; 1356 1357 case IRP_MN_WRITE_CONFIG: 1358 DPRINT("IRP_MN_WRITE_CONFIG\n"); 1359 goto ForwardIrp; 1360 1361 case IRP_MN_EJECT: 1362 DPRINT("IRP_MN_EJECT\n"); 1363 goto ForwardIrp; 1364 1365 case IRP_MN_SET_LOCK: 1366 DPRINT("IRP_MN_SET_LOCK\n"); 1367 goto ForwardIrp; 1368 1369 case IRP_MN_QUERY_ID: 1370 DPRINT("IRP_MN_QUERY_ID\n"); 1371 goto ForwardIrp; 1372 1373 case IRP_MN_QUERY_PNP_DEVICE_STATE: 1374 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 1375 goto ForwardIrp; 1376 1377 case IRP_MN_QUERY_BUS_INFORMATION: 1378 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); 1379 goto ForwardIrp; 1380 1381 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 1382 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 1383 goto ForwardIrp; 1384 1385 case IRP_MN_SURPRISE_REMOVAL: 1386 DPRINT1("IRP_MN_SURPRISE_REMOVAL\n"); 1387 if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED)) 1388 { 1389 USBPORT_InvalidateControllerHandler(FdoDevice, 1390 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE); 1391 } 1392 goto ForwardIrp; 1393 1394 default: 1395 DPRINT("unknown IRP_MN_???\n"); 1396 ForwardIrp: 1397 /* forward irp to next device object */ 1398 IoSkipCurrentIrpStackLocation(Irp); 1399 break; 1400 } 1401 1402 return IoCallDriver(FdoCommonExtension->LowerDevice, Irp); 1403 } 1404 1405 PVOID 1406 NTAPI 1407 USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice, 1408 IN USHORT VendorID, 1409 IN USHORT DeviceID, 1410 IN USHORT RevisionID) 1411 { 1412 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1413 PUSBPORT_REGISTRATION_PACKET Packet; 1414 PVOID Id; 1415 WCHAR Buffer[300] = {0}; 1416 SIZE_T Length = 0; 1417 size_t Remaining = sizeof(Buffer); 1418 PWCHAR EndBuffer; 1419 1420 FdoExtension = FdoDevice->DeviceExtension; 1421 Packet = &FdoExtension->MiniPortInterface->Packet; 1422 1423 DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n", 1424 FdoDevice, 1425 Packet->MiniPortFlags); 1426 1427 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 1428 { 1429 RtlStringCbPrintfExW(Buffer, 1430 Remaining, 1431 &EndBuffer, 1432 &Remaining, 1433 0, 1434 L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x", 1435 VendorID, 1436 DeviceID, 1437 RevisionID); 1438 1439 EndBuffer++; 1440 Remaining -= sizeof(UNICODE_NULL); 1441 1442 RtlStringCbPrintfExW(EndBuffer, 1443 Remaining, 1444 &EndBuffer, 1445 &Remaining, 1446 0, 1447 L"USB\\ROOT_HUB20&VID%04x&PID%04x", 1448 VendorID, 1449 DeviceID); 1450 1451 EndBuffer++; 1452 Remaining -= sizeof(UNICODE_NULL); 1453 1454 RtlStringCbPrintfExW(EndBuffer, 1455 Remaining, 1456 NULL, 1457 &Remaining, 1458 0, 1459 L"USB\\ROOT_HUB20"); 1460 } 1461 else 1462 { 1463 RtlStringCbPrintfExW(Buffer, 1464 Remaining, 1465 &EndBuffer, 1466 &Remaining, 1467 0, 1468 L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x", 1469 VendorID, 1470 DeviceID, 1471 RevisionID); 1472 1473 EndBuffer++; 1474 Remaining -= sizeof(UNICODE_NULL); 1475 1476 RtlStringCbPrintfExW(EndBuffer, 1477 Remaining, 1478 &EndBuffer, 1479 &Remaining, 1480 0, 1481 L"USB\\ROOT_HUB&VID%04x&PID%04x", 1482 VendorID, 1483 DeviceID); 1484 1485 EndBuffer++; 1486 Remaining -= sizeof(UNICODE_NULL); 1487 1488 RtlStringCbPrintfExW(EndBuffer, 1489 Remaining, 1490 NULL, 1491 &Remaining, 1492 0, 1493 L"USB\\ROOT_HUB"); 1494 } 1495 1496 Length = (sizeof(Buffer) - Remaining + 2 * sizeof(UNICODE_NULL)); 1497 1498 /* for debug only */ 1499 if (FALSE) 1500 { 1501 DPRINT("Hardware IDs:\n"); 1502 USBPORT_DumpingIDs(Buffer); 1503 } 1504 1505 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG); 1506 1507 if (!Id) 1508 return NULL; 1509 1510 RtlMoveMemory(Id, Buffer, Length); 1511 1512 return Id; 1513 } 1514 1515 NTSTATUS 1516 NTAPI 1517 USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice, 1518 IN PIRP Irp) 1519 { 1520 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 1521 PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension; 1522 PDEVICE_OBJECT FdoDevice; 1523 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1524 PIO_STACK_LOCATION IoStack; 1525 UCHAR Minor; 1526 NTSTATUS Status; 1527 PPNP_BUS_INFORMATION BusInformation; 1528 PDEVICE_CAPABILITIES DeviceCapabilities; 1529 1530 PdoExtension = PdoDevice->DeviceExtension; 1531 PdoCommonExtension = &PdoExtension->CommonExtension; 1532 1533 FdoDevice = PdoExtension->FdoDevice; 1534 FdoExtension = FdoDevice->DeviceExtension; 1535 1536 IoStack = IoGetCurrentIrpStackLocation(Irp); 1537 Minor = IoStack->MinorFunction; 1538 1539 Status = Irp->IoStatus.Status; 1540 1541 DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor); 1542 1543 switch (Minor) 1544 { 1545 case IRP_MN_START_DEVICE: 1546 DPRINT("IRP_MN_START_DEVICE\n"); 1547 1548 Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice); 1549 1550 if (NT_SUCCESS(Status)) 1551 { 1552 Status = USBPORT_RegisterDeviceInterface(PdoDevice, 1553 PdoDevice, 1554 &GUID_DEVINTERFACE_USB_HUB, 1555 TRUE); 1556 1557 if (NT_SUCCESS(Status)) 1558 { 1559 PdoCommonExtension->DevicePowerState = PowerDeviceD0; 1560 PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED; 1561 } 1562 } 1563 1564 break; 1565 1566 case IRP_MN_QUERY_REMOVE_DEVICE: 1567 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n"); 1568 Status = STATUS_SUCCESS; 1569 break; 1570 1571 case IRP_MN_REMOVE_DEVICE: 1572 DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n"); 1573 //USBPORT_StopRootHub(); 1574 Status = STATUS_SUCCESS; 1575 break; 1576 1577 case IRP_MN_CANCEL_REMOVE_DEVICE: 1578 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n"); 1579 Status = STATUS_SUCCESS; 1580 break; 1581 1582 case IRP_MN_STOP_DEVICE: 1583 DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n"); 1584 //USBPORT_StopRootHub(); 1585 Status = STATUS_SUCCESS; 1586 break; 1587 1588 case IRP_MN_QUERY_STOP_DEVICE: 1589 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n"); 1590 Status = STATUS_SUCCESS; 1591 break; 1592 1593 case IRP_MN_CANCEL_STOP_DEVICE: 1594 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n"); 1595 Status = STATUS_SUCCESS; 1596 break; 1597 1598 case IRP_MN_QUERY_DEVICE_RELATIONS: 1599 { 1600 PDEVICE_RELATIONS DeviceRelations; 1601 1602 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n"); 1603 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 1604 { 1605 break; 1606 } 1607 1608 DeviceRelations = ExAllocatePoolWithTag(PagedPool, 1609 sizeof(DEVICE_RELATIONS), 1610 USB_PORT_TAG); 1611 1612 if (!DeviceRelations) 1613 { 1614 Status = STATUS_INSUFFICIENT_RESOURCES; 1615 Irp->IoStatus.Information = 0; 1616 break; 1617 } 1618 1619 DeviceRelations->Count = 1; 1620 DeviceRelations->Objects[0] = PdoDevice; 1621 1622 ObReferenceObject(PdoDevice); 1623 1624 Status = STATUS_SUCCESS; 1625 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1626 break; 1627 } 1628 1629 case IRP_MN_QUERY_INTERFACE: 1630 DPRINT("IRP_MN_QUERY_INTERFACE\n"); 1631 Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp); 1632 break; 1633 1634 case IRP_MN_QUERY_CAPABILITIES: 1635 DPRINT("IRP_MN_QUERY_CAPABILITIES\n"); 1636 1637 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 1638 1639 RtlCopyMemory(DeviceCapabilities, 1640 &PdoExtension->Capabilities, 1641 sizeof(DEVICE_CAPABILITIES)); 1642 1643 Status = STATUS_SUCCESS; 1644 break; 1645 1646 case IRP_MN_QUERY_RESOURCES: 1647 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n"); 1648 break; 1649 1650 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 1651 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 1652 break; 1653 1654 case IRP_MN_QUERY_DEVICE_TEXT: 1655 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n"); 1656 break; 1657 1658 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 1659 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 1660 break; 1661 1662 case IRP_MN_READ_CONFIG: 1663 DPRINT("IRP_MN_READ_CONFIG\n"); 1664 ASSERT(FALSE); 1665 break; 1666 1667 case IRP_MN_WRITE_CONFIG: 1668 DPRINT("IRP_MN_WRITE_CONFIG\n"); 1669 ASSERT(FALSE); 1670 break; 1671 1672 case IRP_MN_EJECT: 1673 DPRINT("IRP_MN_EJECT\n"); 1674 ASSERT(FALSE); 1675 break; 1676 1677 case IRP_MN_SET_LOCK: 1678 DPRINT("IRP_MN_SET_LOCK\n"); 1679 ASSERT(FALSE); 1680 break; 1681 1682 case IRP_MN_QUERY_ID: 1683 { 1684 ULONG IdType; 1685 LONG Length; 1686 WCHAR Buffer[64] = {0}; 1687 PVOID Id; 1688 1689 Status = STATUS_SUCCESS; 1690 IdType = IoStack->Parameters.QueryId.IdType; 1691 1692 DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType); 1693 1694 if (IdType == BusQueryDeviceID) 1695 { 1696 PUSBPORT_REGISTRATION_PACKET Packet; 1697 Packet = &FdoExtension->MiniPortInterface->Packet; 1698 1699 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 1700 { 1701 RtlStringCbPrintfW(Buffer, 1702 sizeof(Buffer), 1703 L"USB\\ROOT_HUB20"); 1704 } 1705 else 1706 { 1707 RtlStringCbPrintfW(Buffer, 1708 sizeof(Buffer), 1709 L"USB\\ROOT_HUB"); 1710 } 1711 1712 Length = (LONG)(wcslen(Buffer) + 1); 1713 1714 Id = ExAllocatePoolWithTag(PagedPool, 1715 Length * sizeof(WCHAR), 1716 USB_PORT_TAG); 1717 1718 if (Id) 1719 { 1720 RtlZeroMemory(Id, Length * sizeof(WCHAR)); 1721 RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer); 1722 1723 DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n", 1724 Id, 1725 Length); 1726 } 1727 1728 Irp->IoStatus.Information = (ULONG_PTR)Id; 1729 break; 1730 } 1731 1732 if (IdType == BusQueryHardwareIDs) 1733 { 1734 Id = USBPORT_GetDeviceHwIds(FdoDevice, 1735 FdoExtension->VendorID, 1736 FdoExtension->DeviceID, 1737 FdoExtension->RevisionID); 1738 1739 Irp->IoStatus.Information = (ULONG_PTR)Id; 1740 break; 1741 } 1742 1743 if (IdType == BusQueryCompatibleIDs || 1744 IdType == BusQueryInstanceID) 1745 { 1746 Irp->IoStatus.Information = 0; 1747 break; 1748 } 1749 1750 /* IdType == BusQueryDeviceSerialNumber */ 1751 Status = Irp->IoStatus.Status; 1752 break; 1753 } 1754 1755 case IRP_MN_QUERY_PNP_DEVICE_STATE: 1756 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 1757 Status = STATUS_SUCCESS; 1758 break; 1759 1760 case IRP_MN_QUERY_BUS_INFORMATION: 1761 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); 1762 1763 /* Allocate buffer for bus information */ 1764 BusInformation = ExAllocatePoolWithTag(PagedPool, 1765 sizeof(PNP_BUS_INFORMATION), 1766 USB_PORT_TAG); 1767 1768 if (!BusInformation) 1769 { 1770 /* No memory */ 1771 Status = STATUS_INSUFFICIENT_RESOURCES; 1772 break; 1773 } 1774 1775 RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION)); 1776 1777 /* Copy BUS GUID */ 1778 RtlMoveMemory(&BusInformation->BusTypeGuid, 1779 &GUID_BUS_TYPE_USB, 1780 sizeof(GUID)); 1781 1782 /* Set bus type */ 1783 BusInformation->LegacyBusType = PNPBus; 1784 BusInformation->BusNumber = 0; 1785 1786 Status = STATUS_SUCCESS; 1787 Irp->IoStatus.Information = (ULONG_PTR)BusInformation; 1788 break; 1789 1790 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 1791 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 1792 break; 1793 1794 case IRP_MN_SURPRISE_REMOVAL: 1795 DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n"); 1796 Status = STATUS_SUCCESS; 1797 break; 1798 1799 default: 1800 DPRINT("unknown IRP_MN_???\n"); 1801 break; 1802 } 1803 1804 Irp->IoStatus.Status = Status; 1805 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1806 return Status; 1807 } 1808