1 /* 2 * PROJECT: ReactOS USB Hub Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBHub I/O control functions 5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbhub.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_USBHUB_IOCTL 14 #include "dbg_uhub.h" 15 16 NTSTATUS 17 NTAPI 18 USBH_SelectConfigOrInterfaceComplete(IN PDEVICE_OBJECT DeviceObject, 19 IN PIRP Irp, 20 IN PVOID Context) 21 { 22 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 23 PUSBHUB_FDO_EXTENSION HubExtension; 24 PVOID TimeoutContext; // PUSBHUB_BANDWIDTH_TIMEOUT_CONTEXT 25 PUSBHUB_PORT_DATA PortData = NULL; 26 NTSTATUS Status; 27 KIRQL OldIrql; 28 PURB Urb; 29 30 DPRINT("USBH_SelectConfigOrInterfaceComplete ... \n"); 31 32 if (Irp->PendingReturned) 33 { 34 IoMarkIrpPending(Irp); 35 } 36 37 PortExtension = Context; 38 HubExtension = PortExtension->HubExtension; 39 40 ASSERT(PortExtension->PortNumber > 0); 41 42 if (HubExtension) 43 { 44 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1]; 45 } 46 47 Status = Irp->IoStatus.Status; 48 49 if (NT_SUCCESS(Irp->IoStatus.Status)) 50 { 51 KeAcquireSpinLock(&PortExtension->PortTimeoutSpinLock, &OldIrql); 52 53 TimeoutContext = PortExtension->BndwTimeoutContext; 54 55 if (TimeoutContext) 56 { 57 DPRINT1("USBH_SelectConfigOrInterfaceComplete: TimeoutContext != NULL. FIXME\n"); 58 DbgBreakPoint(); 59 } 60 61 KeReleaseSpinLock(&PortExtension->PortTimeoutSpinLock, OldIrql); 62 63 PortExtension->PortPdoFlags &= ~(USBHUB_PDO_FLAG_PORT_RESTORE_FAIL | 64 USBHUB_PDO_FLAG_ALLOC_BNDW_FAILED); 65 66 if (PortData && PortData->ConnectionStatus != DeviceHubNestedTooDeeply) 67 { 68 PortData->ConnectionStatus = DeviceConnected; 69 } 70 } 71 else 72 { 73 Urb = URB_FROM_IRP(Irp); 74 DPRINT1("USBH_SelectConfigOrInterfaceComplete: Status = 0x%lx, UsbdStatus = 0x%lx\n", Status, Urb->UrbHeader.Status); 75 if (Urb->UrbHeader.Status == USBD_STATUS_NO_BANDWIDTH) 76 { 77 DPRINT1("USBH_SelectConfigOrInterfaceComplete: USBD_STATUS_NO_BANDWIDTH. FIXME\n"); 78 DbgBreakPoint(); 79 } 80 } 81 82 return Status; 83 } 84 85 NTSTATUS 86 NTAPI 87 USBH_PdoUrbFilter(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 88 IN PIRP Irp) 89 { 90 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor; 91 PUSBHUB_FDO_EXTENSION HubExtension; 92 PDEVICE_OBJECT DeviceObject; 93 PURB Urb; 94 USHORT Function; 95 ULONG MaxPower; 96 USBD_STATUS UrbStatus; 97 BOOLEAN IsValidConfig; 98 99 HubExtension = PortExtension->HubExtension; 100 DeviceObject = PortExtension->Common.SelfDevice; 101 102 Urb = URB_FROM_IRP(Irp); 103 104 DPRINT_IOCTL("USBH_PdoUrbFilter: Device - %p, Irp - %p, Urb - %p\n", 105 DeviceObject, 106 Irp, 107 Urb); 108 109 if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_PORT_RESTORE_FAIL | 110 USBHUB_PDO_FLAG_PORT_RESSETING)) 111 { 112 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER; 113 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER); 114 return STATUS_INVALID_PARAMETER; 115 } 116 117 Function = Urb->UrbHeader.Function; 118 119 switch (Function) 120 { 121 case URB_FUNCTION_SELECT_CONFIGURATION: 122 { 123 ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor; 124 125 if (ConfigDescriptor) 126 { 127 IsValidConfig = TRUE; 128 129 if (ConfigDescriptor->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) 130 { 131 DPRINT1("USBH_PdoUrbFilter: Not valid Cfg. bDescriptorType\n"); 132 IsValidConfig = FALSE; 133 UrbStatus = USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR; 134 } 135 136 if (ConfigDescriptor->bLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) 137 { 138 DPRINT1("USBH_PdoUrbFilter: Size Cfg. descriptor is too small\n"); 139 IsValidConfig = FALSE; 140 UrbStatus = USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR; 141 } 142 143 if (!IsValidConfig) 144 { 145 Urb->UrbHeader.Status = UrbStatus; 146 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER); 147 return STATUS_INVALID_PARAMETER; 148 } 149 150 MaxPower = 2 * ConfigDescriptor->MaxPower; 151 PortExtension->MaxPower = MaxPower; 152 153 if (HubExtension->MaxPowerPerPort < MaxPower) 154 { 155 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_INSUFFICIENT_PWR; 156 157 DPRINT1("USBH_PdoUrbFilter: USBH_InvalidatePortDeviceState() UNIMPLEMENTED. FIXME\n"); 158 DbgBreakPoint(); 159 160 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER); 161 return STATUS_INVALID_PARAMETER; 162 } 163 } 164 } 165 166 /* fall through */ 167 168 case URB_FUNCTION_SELECT_INTERFACE: 169 { 170 IoCopyCurrentIrpStackLocationToNext(Irp); 171 172 IoSetCompletionRoutine(Irp, 173 USBH_SelectConfigOrInterfaceComplete, 174 PortExtension, 175 TRUE, 176 TRUE, 177 TRUE); 178 179 return IoCallDriver(HubExtension->RootHubPdo2, Irp); 180 } 181 182 case URB_FUNCTION_CONTROL_TRANSFER: 183 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: 184 case URB_FUNCTION_ISOCH_TRANSFER: 185 { 186 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DELETE_PENDING) 187 { 188 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER; 189 USBH_CompleteIrp(Irp, STATUS_DELETE_PENDING); 190 return STATUS_DELETE_PENDING; 191 } 192 193 break; 194 } 195 196 case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR: 197 DPRINT1("USBH_PdoUrbFilter: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR UNIMPLEMENTED. FIXME\n"); 198 USBH_CompleteIrp(Irp, STATUS_NOT_IMPLEMENTED); 199 return STATUS_NOT_IMPLEMENTED; 200 201 default: 202 break; 203 } 204 205 return USBH_PassIrp(HubExtension->RootHubPdo2, Irp); 206 } 207 208 NTSTATUS 209 NTAPI 210 USBH_PdoIoctlSubmitUrb(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 211 IN PIRP Irp) 212 { 213 PUSBHUB_FDO_EXTENSION HubExtension; 214 PURB Urb; 215 NTSTATUS Status; 216 217 DPRINT_IOCTL("USBH_PdoIoctlSubmitUrb ... \n"); 218 219 HubExtension = PortExtension->HubExtension; 220 221 Urb = URB_FROM_IRP(Irp); 222 223 if (PortExtension->DeviceHandle == NULL) 224 { 225 Urb->UrbHeader.UsbdDeviceHandle = NULL; 226 Status = USBH_PassIrp(HubExtension->RootHubPdo2, Irp); 227 } 228 else 229 { 230 Urb->UrbHeader.UsbdDeviceHandle = PortExtension->DeviceHandle; 231 Status = USBH_PdoUrbFilter(PortExtension, Irp); 232 } 233 234 return Status; 235 } 236 237 NTSTATUS 238 NTAPI 239 USBH_PdoIoctlGetPortStatus(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 240 IN PIRP Irp) 241 { 242 PUSBHUB_FDO_EXTENSION HubExtension; 243 PUSBHUB_PORT_DATA PortData; 244 PIO_STACK_LOCATION IoStack; 245 PULONG PortStatus; 246 NTSTATUS Status; 247 248 DPRINT("USBH_PdoIoctlGetPortStatus ... \n"); 249 250 HubExtension = PortExtension->HubExtension; 251 252 InterlockedIncrement(&HubExtension->PendingRequestCount); 253 254 KeWaitForSingleObject(&HubExtension->HubSemaphore, 255 Executive, 256 KernelMode, 257 FALSE, 258 NULL); 259 260 ASSERT(PortExtension->PortNumber > 0); 261 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1]; 262 263 Status = USBH_SyncGetPortStatus(HubExtension, 264 PortExtension->PortNumber, 265 &PortData->PortStatus, 266 sizeof(USB_PORT_STATUS_AND_CHANGE)); 267 268 IoStack = IoGetCurrentIrpStackLocation(Irp); 269 PortStatus = IoStack->Parameters.Others.Argument1; 270 271 *PortStatus = 0; 272 273 if (PortExtension->Common.SelfDevice == PortData->DeviceObject) 274 { 275 if (PortData->PortStatus.PortStatus.Usb20PortStatus.PortEnabledDisabled) 276 { 277 *PortStatus |= USBD_PORT_ENABLED; 278 } 279 280 if (PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus) 281 { 282 *PortStatus |= USBD_PORT_CONNECTED; 283 } 284 } 285 286 KeReleaseSemaphore(&HubExtension->HubSemaphore, 287 LOW_REALTIME_PRIORITY, 288 1, 289 FALSE); 290 291 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 292 { 293 KeSetEvent(&HubExtension->PendingRequestEvent, 294 EVENT_INCREMENT, 295 FALSE); 296 } 297 298 USBH_CompleteIrp(Irp, Status); 299 300 return Status; 301 } 302 303 VOID 304 NTAPI 305 USBH_ResetPortWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 306 IN PVOID Context) 307 { 308 PUSBHUB_RESET_PORT_CONTEXT WorkItemReset; 309 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 310 PUSB_DEVICE_HANDLE DeviceHandle; 311 NTSTATUS Status; 312 USHORT Port; 313 314 DPRINT("USBH_ResetPortWorker ... \n"); 315 316 WorkItemReset = Context; 317 318 PortExtension = WorkItemReset->PortExtension; 319 320 if (!HubExtension) 321 { 322 Status = STATUS_UNSUCCESSFUL; 323 goto Exit; 324 } 325 326 InterlockedIncrement(&HubExtension->PendingRequestCount); 327 328 KeWaitForSingleObject(&HubExtension->HubSemaphore, 329 Executive, 330 KernelMode, 331 FALSE, 332 NULL); 333 334 Port = PortExtension->PortNumber; 335 DeviceHandle = PortExtension->DeviceHandle; 336 337 ASSERT(Port > 0); 338 339 if (PortExtension->Common.SelfDevice == HubExtension->PortData[Port-1].DeviceObject && 340 DeviceHandle != NULL) 341 { 342 USBD_RemoveDeviceEx(HubExtension, 343 DeviceHandle, 344 USBD_MARK_DEVICE_BUSY); 345 346 Status = USBH_ResetDevice(HubExtension, 347 Port, 348 TRUE, 349 FALSE); 350 } 351 else 352 { 353 Status = STATUS_INVALID_PARAMETER; 354 } 355 356 KeReleaseSemaphore(&HubExtension->HubSemaphore, 357 LOW_REALTIME_PRIORITY, 358 1, 359 FALSE); 360 361 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 362 { 363 KeSetEvent(&HubExtension->PendingRequestEvent, 364 EVENT_INCREMENT, 365 FALSE); 366 } 367 368 Exit: 369 370 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESSETING; 371 372 USBH_CompleteIrp(WorkItemReset->Irp, Status); 373 374 WorkItemReset->PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESTORE_FAIL; 375 } 376 377 NTSTATUS 378 NTAPI 379 USBH_PdoIoctlResetPort(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 380 IN PIRP Irp) 381 { 382 PUSBHUB_FDO_EXTENSION HubExtension; 383 PUSBHUB_RESET_PORT_CONTEXT HubWorkItemBuffer; 384 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 385 NTSTATUS Status; 386 387 HubExtension = PortExtension->HubExtension; 388 389 DPRINT("USBH_PdoIoctlResetPort ... \n"); 390 391 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_RESSETING) 392 { 393 Status = STATUS_UNSUCCESSFUL; 394 USBH_CompleteIrp(Irp, Status); 395 return Status; 396 } 397 398 Status = USBH_AllocateWorkItem(HubExtension, 399 &HubIoWorkItem, 400 USBH_ResetPortWorker, 401 sizeof(USBHUB_RESET_PORT_CONTEXT), 402 (PVOID *)&HubWorkItemBuffer, 403 DelayedWorkQueue); 404 405 if (!NT_SUCCESS(Status)) 406 { 407 Status = STATUS_UNSUCCESSFUL; 408 USBH_CompleteIrp(Irp, Status); 409 return Status; 410 } 411 412 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_PORT_RESSETING; 413 IoMarkIrpPending(Irp); 414 415 HubWorkItemBuffer->PortExtension = PortExtension; 416 HubWorkItemBuffer->Irp = Irp; 417 418 Status = STATUS_PENDING; 419 420 USBH_QueueWorkItem(PortExtension->HubExtension, HubIoWorkItem); 421 422 return Status; 423 } 424 425 VOID 426 NTAPI 427 USBH_PortIdleNotificationCancelRoutine(IN PDEVICE_OBJECT Device, 428 IN PIRP Irp) 429 { 430 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 431 PUSBHUB_FDO_EXTENSION HubExtension; 432 PIRP PendingIdleIrp = NULL; 433 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 434 PUSBHUB_IDLE_PORT_CANCEL_CONTEXT HubWorkItemBuffer; 435 NTSTATUS Status; 436 437 DPRINT("USBH_PortIdleNotificationCancelRoutine ... \n"); 438 439 PortExtension = Device->DeviceExtension; 440 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION; 441 442 HubExtension = PortExtension->HubExtension; 443 ASSERT(HubExtension); 444 445 PortExtension->IdleNotificationIrp = NULL; 446 447 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) 448 { 449 PendingIdleIrp = HubExtension->PendingIdleIrp; 450 HubExtension->PendingIdleIrp = NULL; 451 } 452 453 IoReleaseCancelSpinLock(Irp->CancelIrql); 454 455 if (PendingIdleIrp) 456 { 457 USBH_HubCancelIdleIrp(HubExtension, PendingIdleIrp); 458 } 459 460 if (HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0) 461 { 462 goto ErrorExit; 463 } 464 465 Status = USBH_AllocateWorkItem(HubExtension, 466 &HubIoWorkItem, 467 USBH_IdleCancelPowerHubWorker, 468 sizeof(USBHUB_IDLE_PORT_CANCEL_CONTEXT), 469 (PVOID *)&HubWorkItemBuffer, 470 DelayedWorkQueue); 471 472 if (NT_SUCCESS(Status)) 473 { 474 HubWorkItemBuffer->Irp = Irp; 475 USBH_QueueWorkItem(HubExtension, HubIoWorkItem); 476 return; 477 } 478 479 ErrorExit: 480 481 Irp->IoStatus.Status = STATUS_CANCELLED; 482 IoCompleteRequest(Irp, IO_NO_INCREMENT); 483 } 484 485 NTSTATUS 486 NTAPI 487 USBH_PortIdleNotificationRequest(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 488 IN PIRP Irp) 489 { 490 PUSBHUB_FDO_EXTENSION HubExtension; 491 PIO_STACK_LOCATION IoStack; 492 PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo; 493 NTSTATUS Status; 494 KIRQL Irql; 495 496 DPRINT("USBH_PortIdleNotificationRequest ... \n"); 497 498 HubExtension = PortExtension->HubExtension; 499 500 IoAcquireCancelSpinLock(&Irql); 501 502 if (PortExtension->IdleNotificationIrp) 503 { 504 IoReleaseCancelSpinLock(Irql); 505 Irp->IoStatus.Status = STATUS_DEVICE_BUSY; 506 IoCompleteRequest(Irp, IO_NO_INCREMENT); 507 return STATUS_DEVICE_BUSY; 508 } 509 510 IoStack = IoGetCurrentIrpStackLocation(Irp); 511 IdleCallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 512 513 if (!IdleCallbackInfo || !IdleCallbackInfo->IdleCallback) 514 { 515 IoReleaseCancelSpinLock(Irql); 516 517 Status = STATUS_NO_CALLBACK_ACTIVE; 518 Irp->IoStatus.Status = Status; 519 IoCompleteRequest(Irp, IO_NO_INCREMENT); 520 521 return Status; 522 } 523 524 IoSetCancelRoutine(Irp, USBH_PortIdleNotificationCancelRoutine); 525 526 if (Irp->Cancel) 527 { 528 if (IoSetCancelRoutine(Irp, NULL)) 529 { 530 IoReleaseCancelSpinLock(Irql); 531 Status = STATUS_CANCELLED; 532 Irp->IoStatus.Status = STATUS_CANCELLED; 533 IoCompleteRequest(Irp, IO_NO_INCREMENT); 534 } 535 else 536 { 537 IoMarkIrpPending(Irp); 538 IoReleaseCancelSpinLock(Irql); 539 Status = STATUS_PENDING; 540 } 541 } 542 else 543 { 544 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_IDLE_NOTIFICATION; 545 546 PortExtension->IdleNotificationIrp = Irp; 547 IoMarkIrpPending(Irp); 548 549 IoReleaseCancelSpinLock(Irql); 550 Status = STATUS_PENDING; 551 552 DPRINT("USBH_PortIdleNotificationRequest: IdleNotificationIrp - %p\n", 553 PortExtension->IdleNotificationIrp); 554 555 USBH_CheckIdleDeferred(HubExtension); 556 } 557 558 return Status; 559 } 560 561 NTSTATUS 562 NTAPI 563 USBH_IoctlGetNodeName(IN PUSBHUB_FDO_EXTENSION HubExtension, 564 IN PIRP Irp) 565 { 566 PUSB_NODE_CONNECTION_NAME ConnectionName; 567 PDEVICE_OBJECT PortDevice; 568 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 569 size_t LengthSkip; 570 PWCHAR Buffer; 571 ULONG BufferLength; 572 PWCHAR BufferEnd; 573 ULONG_PTR LengthReturned; 574 size_t LengthName; 575 ULONG Length; 576 NTSTATUS Status; 577 PIO_STACK_LOCATION IoStack; 578 ULONG_PTR Information; 579 580 DPRINT("USBH_IoctlGetNodeName ... \n"); 581 582 Status = STATUS_SUCCESS; 583 584 ConnectionName = Irp->AssociatedIrp.SystemBuffer; 585 586 IoStack = IoGetCurrentIrpStackLocation(Irp); 587 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 588 589 if (Length < sizeof(USB_NODE_CONNECTION_NAME)) 590 { 591 Status = STATUS_BUFFER_TOO_SMALL; 592 Information = Irp->IoStatus.Information; 593 goto Exit; 594 } 595 596 if (ConnectionName->ConnectionIndex == 0 || 597 ConnectionName->ConnectionIndex > HubExtension->HubDescriptor->bNumberOfPorts) 598 { 599 Status = STATUS_INVALID_PARAMETER; 600 Information = Irp->IoStatus.Information; 601 goto Exit; 602 } 603 604 PortDevice = HubExtension->PortData[ConnectionName->ConnectionIndex - 1].DeviceObject; 605 606 if (!PortDevice) 607 { 608 ConnectionName->NodeName[0] = 0; 609 ConnectionName->ActualLength = sizeof(USB_NODE_CONNECTION_NAME); 610 611 Information = sizeof(USB_NODE_CONNECTION_NAME); 612 goto Exit; 613 } 614 615 PortExtension = PortDevice->DeviceExtension; 616 617 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE) || 618 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DEVICE_STARTED) || 619 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE)) 620 { 621 ConnectionName->NodeName[0] = 0; 622 ConnectionName->ActualLength = sizeof(USB_NODE_CONNECTION_NAME); 623 624 Information = sizeof(USB_NODE_CONNECTION_NAME); 625 goto Exit; 626 } 627 628 Buffer = PortExtension->SymbolicLinkName.Buffer; 629 BufferLength = PortExtension->SymbolicLinkName.Length; 630 631 ASSERT(Buffer[BufferLength / sizeof(WCHAR)] == UNICODE_NULL); 632 633 LengthSkip = 0; 634 635 if (*Buffer == L'\\') 636 { 637 BufferEnd = wcschr(Buffer + 1, L'\\'); 638 639 if (BufferEnd != NULL) 640 { 641 LengthSkip = (BufferEnd + 1 - Buffer) * sizeof(WCHAR); 642 } 643 else 644 { 645 LengthSkip = PortExtension->SymbolicLinkName.Length; 646 } 647 } 648 649 LengthName = BufferLength - LengthSkip; 650 651 ConnectionName->ActualLength = 0; 652 653 RtlZeroMemory(ConnectionName->NodeName, 654 Length - FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName)); 655 656 LengthReturned = sizeof(USB_NODE_CONNECTION_NAME) + LengthName; 657 658 if (Length < LengthReturned) 659 { 660 ConnectionName->NodeName[0] = 0; 661 ConnectionName->ActualLength = LengthReturned; 662 663 Information = sizeof(USB_NODE_CONNECTION_NAME); 664 goto Exit; 665 } 666 667 RtlCopyMemory(&ConnectionName->NodeName[0], 668 &Buffer[LengthSkip / sizeof(WCHAR)], 669 LengthName); 670 671 ConnectionName->ActualLength = LengthReturned; 672 673 Status = STATUS_SUCCESS; 674 Information = LengthReturned; 675 676 Exit: 677 Irp->IoStatus.Information = Information; 678 USBH_CompleteIrp(Irp, Status); 679 return Status; 680 } 681 682 NTSTATUS 683 NTAPI 684 USBH_IoctlGetNodeInformation(IN PUSBHUB_FDO_EXTENSION HubExtension, 685 IN PIRP Irp) 686 { 687 PUSB_NODE_INFORMATION NodeInfo; 688 PIO_STACK_LOCATION IoStack; 689 ULONG BufferLength; 690 NTSTATUS Status; 691 BOOLEAN HubIsBusPowered; 692 693 DPRINT("USBH_IoctlGetNodeInformation ... \n"); 694 695 Status = STATUS_SUCCESS; 696 697 NodeInfo = Irp->AssociatedIrp.SystemBuffer; 698 699 IoStack = IoGetCurrentIrpStackLocation(Irp); 700 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 701 702 RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, BufferLength); 703 704 if (BufferLength < sizeof(USB_NODE_INFORMATION)) 705 { 706 Status = STATUS_BUFFER_TOO_SMALL; 707 USBH_CompleteIrp(Irp, Status); 708 return Status; 709 } 710 711 NodeInfo->NodeType = UsbHub; 712 713 RtlCopyMemory(&NodeInfo->u.HubInformation.HubDescriptor, 714 HubExtension->HubDescriptor, 715 sizeof(USB_HUB_DESCRIPTOR)); 716 717 HubIsBusPowered = USBH_HubIsBusPowered(HubExtension->Common.SelfDevice, 718 HubExtension->HubConfigDescriptor); 719 720 NodeInfo->u.HubInformation.HubIsBusPowered = HubIsBusPowered; 721 722 Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION); 723 724 USBH_CompleteIrp(Irp, Status); 725 726 return Status; 727 } 728 729 NTSTATUS 730 NTAPI 731 USBH_IoctlGetHubCapabilities(IN PUSBHUB_FDO_EXTENSION HubExtension, 732 IN PIRP Irp) 733 { 734 PUSB_HUB_CAPABILITIES Capabilities; 735 PIO_STACK_LOCATION IoStack; 736 ULONG BufferLength; 737 ULONG Length; 738 USB_HUB_CAPABILITIES HubCaps; 739 740 DPRINT("USBH_IoctlGetHubCapabilities ... \n"); 741 742 Capabilities = Irp->AssociatedIrp.SystemBuffer; 743 744 HubCaps.HubIs2xCapable = (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) == 745 USBHUB_FDO_FLAG_USB20_HUB; 746 747 IoStack = IoGetCurrentIrpStackLocation(Irp); 748 749 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 750 751 if (BufferLength == 0) 752 { 753 Irp->IoStatus.Information = BufferLength; 754 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER); 755 return STATUS_INVALID_PARAMETER; 756 } 757 758 if (BufferLength <= sizeof(HubCaps)) 759 { 760 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 761 } 762 else 763 { 764 Length = sizeof(HubCaps); 765 } 766 767 RtlZeroMemory(Capabilities, BufferLength); 768 RtlCopyMemory(Capabilities, &HubCaps, Length); 769 770 Irp->IoStatus.Information = Length; 771 772 USBH_CompleteIrp(Irp, STATUS_SUCCESS); 773 774 return STATUS_SUCCESS; 775 } 776 777 NTSTATUS 778 NTAPI 779 USBH_IoctlGetNodeConnectionAttributes(IN PUSBHUB_FDO_EXTENSION HubExtension, 780 IN PIRP Irp) 781 { 782 PUSB_NODE_CONNECTION_ATTRIBUTES Attributes; 783 ULONG ConnectionIndex; 784 ULONG NumPorts; 785 NTSTATUS Status; 786 PUSBHUB_PORT_DATA PortData; 787 PIO_STACK_LOCATION IoStack; 788 ULONG BufferLength; 789 790 DPRINT("USBH_IoctlGetNodeConnectionAttributes ... \n"); 791 792 IoStack = IoGetCurrentIrpStackLocation(Irp); 793 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 794 795 if (BufferLength < sizeof(USB_NODE_CONNECTION_ATTRIBUTES)) 796 { 797 Status = STATUS_BUFFER_TOO_SMALL; 798 goto Exit; 799 } 800 801 Attributes = Irp->AssociatedIrp.SystemBuffer; 802 803 ConnectionIndex = Attributes->ConnectionIndex; 804 RtlZeroMemory(Attributes, BufferLength); 805 Attributes->ConnectionIndex = ConnectionIndex; 806 807 Status = STATUS_INVALID_PARAMETER; 808 809 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 810 811 if (NumPorts == 0 || 812 ConnectionIndex == 0 || 813 ConnectionIndex > NumPorts) 814 { 815 goto Exit; 816 } 817 818 PortData = HubExtension->PortData + (ConnectionIndex - 1); 819 820 Attributes->ConnectionStatus = PortData->ConnectionStatus; 821 Attributes->PortAttributes = PortData->PortAttributes; 822 823 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_ATTRIBUTES); 824 Status = STATUS_SUCCESS; 825 826 Exit: 827 828 USBH_CompleteIrp(Irp, Status); 829 return Status; 830 } 831 832 NTSTATUS 833 NTAPI 834 USBH_IoctlGetNodeConnectionInformation(IN PUSBHUB_FDO_EXTENSION HubExtension, 835 IN PIRP Irp, 836 IN BOOLEAN IsExt) 837 { 838 PUSBHUB_PORT_DATA PortData; 839 ULONG BufferLength; 840 PUSB_NODE_CONNECTION_INFORMATION_EX Info; 841 ULONG ConnectionIndex; 842 ULONG NumPorts; 843 NTSTATUS Status; 844 PDEVICE_OBJECT DeviceObject; 845 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 846 PIO_STACK_LOCATION IoStack; 847 848 DPRINT("USBH_IoctlGetNodeConnectionInformation ... \n"); 849 850 IoStack = IoGetCurrentIrpStackLocation(Irp); 851 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 852 853 if (BufferLength < (ULONG)FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX, 854 PipeList)) 855 { 856 Status = STATUS_BUFFER_TOO_SMALL; 857 goto Exit; 858 } 859 860 Info = Irp->AssociatedIrp.SystemBuffer; 861 862 ConnectionIndex = Info->ConnectionIndex; 863 RtlZeroMemory(Info, BufferLength); 864 Info->ConnectionIndex = ConnectionIndex; 865 866 Status = STATUS_INVALID_PARAMETER; 867 868 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 869 870 if (NumPorts == 0 || 871 ConnectionIndex == 0 || 872 ConnectionIndex > NumPorts) 873 { 874 goto Exit; 875 } 876 877 PortData = HubExtension->PortData + (ConnectionIndex - 1); 878 DeviceObject = PortData->DeviceObject; 879 880 if (!DeviceObject) 881 { 882 Info->ConnectionStatus = PortData->ConnectionStatus; 883 884 Irp->IoStatus.Information = FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX, 885 PipeList); 886 Status = STATUS_SUCCESS; 887 goto Exit; 888 } 889 890 PortExtension = DeviceObject->DeviceExtension; 891 892 Info->ConnectionStatus = PortData->ConnectionStatus; 893 894 Info->DeviceIsHub = (PortExtension->PortPdoFlags & 895 USBHUB_PDO_FLAG_HUB_DEVICE) == 896 USBHUB_PDO_FLAG_HUB_DEVICE; 897 898 RtlCopyMemory(&Info->DeviceDescriptor, 899 &PortExtension->DeviceDescriptor, 900 sizeof(USB_DEVICE_DESCRIPTOR)); 901 902 if (PortExtension->DeviceHandle) 903 { 904 Status = USBD_GetDeviceInformationEx(PortExtension, 905 HubExtension, 906 Info, 907 BufferLength, 908 PortExtension->DeviceHandle); 909 } 910 else 911 { 912 Status = STATUS_SUCCESS; 913 } 914 915 if (NT_SUCCESS(Status)) 916 { 917 if (!IsExt) 918 { 919 /* IOCTL_USB_GET_NODE_CONNECTION_INFORMATION request reports 920 only low and full speed connections. Info->Speed member 921 is Info->LowSpeed in the non-EX version of the structure */ 922 923 Info->Speed = (Info->Speed == UsbLowSpeed); 924 } 925 926 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + 927 (Info->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFO); 928 goto Exit; 929 } 930 931 if (Status != STATUS_BUFFER_TOO_SMALL) 932 { 933 goto Exit; 934 } 935 936 Irp->IoStatus.Information = FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX, 937 PipeList); 938 Status = STATUS_SUCCESS; 939 940 Exit: 941 USBH_CompleteIrp(Irp, Status); 942 return Status; 943 } 944 945 NTSTATUS 946 NTAPI 947 USBH_IoctlGetNodeConnectionDriverKeyName(IN PUSBHUB_FDO_EXTENSION HubExtension, 948 IN PIRP Irp) 949 { 950 PUSBHUB_PORT_DATA PortData; 951 PDEVICE_OBJECT PortDevice; 952 ULONG Length; 953 ULONG ResultLength; 954 NTSTATUS Status; 955 PIO_STACK_LOCATION IoStack; 956 ULONG BufferLength; 957 PUSB_NODE_CONNECTION_DRIVERKEY_NAME KeyName; 958 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 959 960 DPRINT("USBH_IoctlGetNodeConnectionDriverKeyName ... \n"); 961 962 IoStack = IoGetCurrentIrpStackLocation(Irp); 963 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 964 965 if (BufferLength < sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) || 966 HubExtension->HubDescriptor->bNumberOfPorts == 0) 967 { 968 Status = STATUS_BUFFER_TOO_SMALL; 969 goto Exit; 970 } 971 972 KeyName = Irp->AssociatedIrp.SystemBuffer; 973 Status = STATUS_INVALID_PARAMETER; 974 975 PortData = &HubExtension->PortData[KeyName->ConnectionIndex - 1]; 976 PortDevice = PortData->DeviceObject; 977 978 if (!PortDevice) 979 { 980 goto Exit; 981 } 982 983 PortExtension = PortDevice->DeviceExtension; 984 985 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_ENUMERATED)) 986 { 987 Status = STATUS_INVALID_DEVICE_STATE; 988 goto Exit; 989 } 990 991 ResultLength = BufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); 992 993 Status = IoGetDeviceProperty(PortDevice, 994 DevicePropertyDriverKeyName, 995 BufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME), 996 &KeyName->DriverKeyName, 997 &ResultLength); 998 999 if (Status == STATUS_BUFFER_TOO_SMALL) 1000 { 1001 Status = STATUS_SUCCESS; 1002 } 1003 1004 Length = ResultLength + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); 1005 KeyName->ActualLength = Length; 1006 1007 if (BufferLength < Length) 1008 { 1009 KeyName->DriverKeyName[0] = 0; 1010 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); 1011 } 1012 else 1013 { 1014 Irp->IoStatus.Information = Length; 1015 } 1016 1017 Exit: 1018 USBH_CompleteIrp(Irp, Status); 1019 return Status; 1020 } 1021 1022 NTSTATUS 1023 NTAPI 1024 USBH_IoctlGetDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension, 1025 IN PIRP Irp) 1026 { 1027 ULONG BufferLength; 1028 PUSBHUB_PORT_DATA PortData; 1029 PUSB_DESCRIPTOR_REQUEST UsbRequest; 1030 PDEVICE_OBJECT PortDevice; 1031 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1032 struct _URB_CONTROL_TRANSFER * Urb; 1033 NTSTATUS Status; 1034 ULONG RequestBufferLength; 1035 PIO_STACK_LOCATION IoStack; 1036 ULONG NumPorts; 1037 1038 IoStack = IoGetCurrentIrpStackLocation(Irp); 1039 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 1040 1041 DPRINT("USBH_IoctlGetDescriptor: BufferLength - %x\n", BufferLength); 1042 1043 if (BufferLength < sizeof(USB_DESCRIPTOR_REQUEST)) 1044 { 1045 Status = STATUS_BUFFER_TOO_SMALL; 1046 goto Exit; 1047 } 1048 1049 UsbRequest = Irp->AssociatedIrp.SystemBuffer; 1050 RequestBufferLength = UsbRequest->SetupPacket.wLength; 1051 1052 if (RequestBufferLength > BufferLength - 1053 FIELD_OFFSET(USB_DESCRIPTOR_REQUEST, Data)) 1054 { 1055 DPRINT("USBH_IoctlGetDescriptor: RequestBufferLength - %x\n", 1056 RequestBufferLength); 1057 1058 Status = STATUS_BUFFER_TOO_SMALL; 1059 goto Exit; 1060 } 1061 1062 Status = STATUS_INVALID_PARAMETER; 1063 1064 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 1065 1066 if (NumPorts == 0 || 1067 UsbRequest->ConnectionIndex == 0 || 1068 UsbRequest->ConnectionIndex > NumPorts) 1069 { 1070 goto Exit; 1071 } 1072 1073 PortData = HubExtension->PortData + (UsbRequest->ConnectionIndex - 1); 1074 PortDevice = PortData->DeviceObject; 1075 1076 if (!PortDevice) 1077 { 1078 goto Exit; 1079 } 1080 1081 PortExtension = PortDevice->DeviceExtension; 1082 1083 if (UsbRequest->SetupPacket.bmRequest == USB_CONFIGURATION_DESCRIPTOR_TYPE && 1084 RequestBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)) 1085 { 1086 Status = STATUS_SUCCESS; 1087 1088 RtlCopyMemory(&UsbRequest->Data[0], 1089 &PortExtension->ConfigDescriptor, 1090 sizeof(USB_CONFIGURATION_DESCRIPTOR)); 1091 1092 Irp->IoStatus.Information = sizeof(USB_DESCRIPTOR_REQUEST) - sizeof(UCHAR) + 1093 sizeof(USB_CONFIGURATION_DESCRIPTOR); 1094 goto Exit; 1095 } 1096 1097 Urb = ExAllocatePoolWithTag(NonPagedPool, 1098 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), 1099 USB_HUB_TAG); 1100 1101 if (!Urb) 1102 { 1103 Status = STATUS_INSUFFICIENT_RESOURCES; 1104 goto Exit; 1105 } 1106 1107 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 1108 1109 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; 1110 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 1111 1112 Urb->TransferBuffer = &UsbRequest->Data[0]; 1113 Urb->TransferBufferLength = RequestBufferLength; 1114 Urb->TransferBufferMDL = NULL; 1115 Urb->UrbLink = NULL; 1116 1117 RtlCopyMemory(Urb->SetupPacket, 1118 &UsbRequest->SetupPacket, 1119 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); 1120 1121 Status = USBH_SyncSubmitUrb(PortExtension->Common.SelfDevice, 1122 (PURB)Urb); 1123 1124 Irp->IoStatus.Information = (sizeof(USB_DESCRIPTOR_REQUEST) - sizeof(UCHAR)) + 1125 Urb->TransferBufferLength; 1126 1127 ExFreePoolWithTag(Urb, USB_HUB_TAG); 1128 1129 Exit: 1130 USBH_CompleteIrp(Irp, Status); 1131 return Status; 1132 } 1133 1134 NTSTATUS 1135 NTAPI 1136 USBH_DeviceControl(IN PUSBHUB_FDO_EXTENSION HubExtension, 1137 IN PIRP Irp) 1138 { 1139 NTSTATUS Status = STATUS_DEVICE_BUSY; 1140 PIO_STACK_LOCATION IoStack; 1141 ULONG ControlCode; 1142 BOOLEAN IsCheckHubIdle = FALSE; 1143 1144 DPRINT("USBH_DeviceControl: HubExtension - %p, Irp - %p\n", 1145 HubExtension, 1146 Irp); 1147 1148 IoStack = IoGetCurrentIrpStackLocation(Irp); 1149 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; 1150 DPRINT("USBH_DeviceControl: ControlCode - %lX\n", ControlCode); 1151 1152 if ((HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0) && 1153 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)) 1154 { 1155 IsCheckHubIdle = TRUE; 1156 USBH_HubSetD0(HubExtension); 1157 } 1158 1159 switch (ControlCode) 1160 { 1161 case IOCTL_USB_GET_HUB_CAPABILITIES: 1162 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_HUB_CAPABILITIES\n"); 1163 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1164 { 1165 Status = USBH_IoctlGetHubCapabilities(HubExtension, Irp); 1166 break; 1167 } 1168 1169 USBH_CompleteIrp(Irp, Status); 1170 break; 1171 1172 case IOCTL_USB_HUB_CYCLE_PORT: 1173 DPRINT1("USBH_DeviceControl: IOCTL_USB_HUB_CYCLE_PORT UNIMPLEMENTED. FIXME\n"); 1174 DbgBreakPoint(); 1175 break; 1176 1177 case IOCTL_USB_GET_NODE_INFORMATION: 1178 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_INFORMATION\n"); 1179 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1180 { 1181 Status = USBH_IoctlGetNodeInformation(HubExtension, Irp); 1182 break; 1183 } 1184 1185 USBH_CompleteIrp(Irp, Status); 1186 break; 1187 1188 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION: 1189 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n"); 1190 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1191 { 1192 Status = USBH_IoctlGetNodeConnectionInformation(HubExtension, 1193 Irp, 1194 FALSE); 1195 break; 1196 } 1197 1198 USBH_CompleteIrp(Irp, Status); 1199 break; 1200 1201 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX: 1202 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n"); 1203 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1204 { 1205 Status = USBH_IoctlGetNodeConnectionInformation(HubExtension, 1206 Irp, 1207 TRUE); 1208 break; 1209 } 1210 1211 USBH_CompleteIrp(Irp, Status); 1212 break; 1213 1214 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES: 1215 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n"); 1216 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1217 { 1218 Status = USBH_IoctlGetNodeConnectionAttributes(HubExtension, Irp); 1219 break; 1220 } 1221 1222 USBH_CompleteIrp(Irp, Status); 1223 break; 1224 1225 case IOCTL_USB_GET_NODE_CONNECTION_NAME: 1226 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_NAME\n"); 1227 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1228 { 1229 Status = USBH_IoctlGetNodeName(HubExtension, Irp); 1230 break; 1231 } 1232 1233 USBH_CompleteIrp(Irp, Status); 1234 break; 1235 1236 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME: 1237 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n"); 1238 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1239 { 1240 Status = USBH_IoctlGetNodeConnectionDriverKeyName(HubExtension, Irp); 1241 break; 1242 } 1243 1244 USBH_CompleteIrp(Irp, Status); 1245 break; 1246 1247 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION: 1248 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n"); 1249 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 1250 { 1251 Status = USBH_IoctlGetDescriptor(HubExtension, Irp); 1252 break; 1253 } 1254 1255 USBH_CompleteIrp(Irp, Status); 1256 break; 1257 1258 case IOCTL_KS_PROPERTY: 1259 DPRINT("USBH_DeviceControl: IOCTL_KS_PROPERTY\n"); 1260 Status = STATUS_INVALID_DEVICE_REQUEST; 1261 USBH_CompleteIrp(Irp, Status); 1262 break; 1263 1264 default: 1265 DPRINT1("USBH_DeviceControl: Unhandled IOCTL_ - %lX\n", ControlCode); 1266 Status = USBH_PassIrp(HubExtension->RootHubPdo, Irp); 1267 break; 1268 } 1269 1270 if (IsCheckHubIdle) 1271 { 1272 USBH_CheckHubIdle(HubExtension); 1273 } 1274 1275 return Status; 1276 } 1277 1278 NTSTATUS 1279 NTAPI 1280 USBH_PdoInternalControl(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 1281 IN PIRP Irp) 1282 { 1283 PUSBHUB_FDO_EXTENSION HubExtension; 1284 NTSTATUS Status = STATUS_NOT_SUPPORTED; 1285 ULONG ControlCode; 1286 PIO_STACK_LOCATION IoStack; 1287 PULONG HubCount; 1288 1289 DPRINT_IOCTL("USBH_PdoInternalControl: PortExtension - %p, Irp - %p\n", 1290 PortExtension, 1291 Irp); 1292 1293 HubExtension = PortExtension->HubExtension; 1294 1295 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_NOT_CONNECTED) 1296 { 1297 Status = STATUS_DEVICE_NOT_CONNECTED; 1298 goto Exit; 1299 } 1300 1301 if (PortExtension->CurrentPowerState.DeviceState != PowerDeviceD0) 1302 { 1303 Status = STATUS_DEVICE_POWERED_OFF; 1304 goto Exit; 1305 } 1306 1307 IoStack = IoGetCurrentIrpStackLocation(Irp); 1308 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; 1309 1310 if (ControlCode == IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO) 1311 { 1312 HubExtension = PortExtension->RootHubExtension; 1313 DPRINT("USBH_PdoInternalControl: HubExtension - %p\n", HubExtension); 1314 } 1315 1316 if (!HubExtension) 1317 { 1318 Status = STATUS_DEVICE_BUSY; 1319 goto Exit; 1320 } 1321 1322 switch (ControlCode) 1323 { 1324 case IOCTL_INTERNAL_USB_SUBMIT_URB: 1325 return USBH_PdoIoctlSubmitUrb(PortExtension, Irp); 1326 1327 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: 1328 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n"); 1329 return USBH_PortIdleNotificationRequest(PortExtension, Irp); 1330 1331 case IOCTL_INTERNAL_USB_GET_PORT_STATUS: 1332 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_PORT_STATUS\n"); 1333 return USBH_PdoIoctlGetPortStatus(PortExtension, Irp); 1334 1335 case IOCTL_INTERNAL_USB_RESET_PORT: 1336 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_RESET_PORT\n"); 1337 return USBH_PdoIoctlResetPort(PortExtension, Irp); 1338 1339 case IOCTL_INTERNAL_USB_ENABLE_PORT: 1340 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_ENABLE_PORT\n"); 1341 DbgBreakPoint(); 1342 break; 1343 1344 case IOCTL_INTERNAL_USB_CYCLE_PORT: 1345 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_CYCLE_PORT\n"); 1346 DbgBreakPoint(); 1347 break; 1348 1349 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: 1350 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); 1351 *(PVOID *)IoStack->Parameters.Others.Argument1 = PortExtension->DeviceHandle; 1352 Status = STATUS_SUCCESS; 1353 break; 1354 1355 case IOCTL_INTERNAL_USB_GET_HUB_COUNT: 1356 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_HUB_COUNT. PortPdoFlags - %lX\n", 1357 PortExtension->PortPdoFlags); 1358 1359 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE)) 1360 { 1361 Status = STATUS_INVALID_PARAMETER; 1362 break; 1363 } 1364 1365 HubCount = IoStack->Parameters.Others.Argument1; 1366 1367 ++*HubCount; 1368 1369 Status = USBH_SyncGetHubCount(HubExtension->LowerDevice, 1370 HubCount); 1371 1372 DPRINT("USBH_PdoInternalControl: *HubCount - %x\n", *HubCount); 1373 break; 1374 1375 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO: 1376 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO. PortPdoFlags - %lX\n", 1377 PortExtension->PortPdoFlags); 1378 1379 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE)) 1380 { 1381 DbgBreakPoint(); 1382 Status = STATUS_SUCCESS; 1383 1384 *(PVOID *)IoStack->Parameters.Others.Argument1 = NULL; 1385 1386 USBH_CompleteIrp(Irp, Status); 1387 break; 1388 } 1389 1390 ASSERT(HubExtension->RootHubPdo); 1391 return USBH_PassIrp(HubExtension->RootHubPdo, Irp); 1392 1393 case IOCTL_INTERNAL_USB_GET_HUB_NAME: 1394 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_HUB_NAME\n"); 1395 DbgBreakPoint(); 1396 break; 1397 1398 case IOCTL_GET_HCD_DRIVERKEY_NAME: 1399 DPRINT1("USBH_PdoInternalControl: IOCTL_GET_HCD_DRIVERKEY_NAME\n"); 1400 DbgBreakPoint(); 1401 break; 1402 1403 case IOCTL_INTERNAL_USB_GET_BUS_INFO: 1404 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_BUS_INFO\n"); 1405 DbgBreakPoint(); 1406 break; 1407 1408 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: 1409 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n"); 1410 DbgBreakPoint(); 1411 break; 1412 1413 default: 1414 DPRINT1("USBH_PdoInternalControl: unhandled IOCTL_ - %lX\n", ControlCode); 1415 break; 1416 } 1417 1418 Exit: 1419 USBH_CompleteIrp(Irp, Status); 1420 return Status; 1421 } 1422