1 /* 2 * PROJECT: ReactOS USB Port Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBPort root hub implementation 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 RHSTATUS 17 NTAPI 18 USBPORT_MPStatusToRHStatus(IN MPSTATUS MPStatus) 19 { 20 RHSTATUS RHStatus = RH_STATUS_SUCCESS; 21 22 //DPRINT("USBPORT_MPStatusToRHStatus: MPStatus - %x\n", MPStatus); 23 24 if (MPStatus) 25 { 26 RHStatus = (MPStatus != MP_STATUS_FAILURE); 27 ++RHStatus; 28 } 29 30 return RHStatus; 31 } 32 33 MPSTATUS 34 NTAPI 35 USBPORT_RH_SetFeatureUSB2PortPower(IN PDEVICE_OBJECT FdoDevice, 36 IN USHORT Port) 37 { 38 PUSBPORT_DEVICE_EXTENSION FdoExtension; 39 PUSBPORT_REGISTRATION_PACKET Packet; 40 PDEVICE_RELATIONS CompanionControllersList; 41 PUSBPORT_REGISTRATION_PACKET CompanionPacket; 42 PDEVICE_OBJECT CompanionFdoDevice; 43 PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension; 44 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 45 USHORT ix; 46 PDEVICE_OBJECT * Entry; 47 ULONG NumController = 0; 48 49 DPRINT("USBPORT_RootHub_PowerUsb2Port: FdoDevice - %p, Port - %p\n", 50 FdoDevice, 51 Port); 52 53 FdoExtension = FdoDevice->DeviceExtension; 54 Packet = &FdoExtension->MiniPortInterface->Packet; 55 56 CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice, 57 FALSE, 58 TRUE); 59 60 if (!CompanionControllersList) 61 { 62 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); 63 return MP_STATUS_SUCCESS; 64 } 65 66 Entry = &CompanionControllersList->Objects[0]; 67 68 while (NumController < CompanionControllersList->Count) 69 { 70 CompanionFdoDevice = *Entry; 71 72 CompanionFdoExtension = CompanionFdoDevice->DeviceExtension; 73 CompanionPacket = &CompanionFdoExtension->MiniPortInterface->Packet; 74 75 PdoExtension = CompanionFdoExtension->RootHubPdo->DeviceExtension; 76 77 for (ix = 0; 78 (PdoExtension->CommonExtension.PnpStateFlags & USBPORT_PNP_STATE_STARTED) && 79 ix < PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts; 80 ++ix) 81 { 82 CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt, 83 ix + 1); 84 } 85 86 ++NumController; 87 ++Entry; 88 } 89 90 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); 91 92 if (CompanionControllersList) 93 { 94 ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG); 95 } 96 97 return MP_STATUS_SUCCESS; 98 } 99 100 RHSTATUS 101 NTAPI 102 USBPORT_RootHubClassCommand(IN PDEVICE_OBJECT FdoDevice, 103 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, 104 IN PVOID Buffer, 105 IN PULONG BufferLength) 106 { 107 PUSBPORT_DEVICE_EXTENSION FdoExtension; 108 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 109 PUSBPORT_REGISTRATION_PACKET Packet; 110 USHORT Port; 111 USHORT Feature; 112 MPSTATUS MPStatus; 113 RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL; 114 KIRQL OldIrql; 115 116 DPRINT("USBPORT_RootHubClassCommand: USB command - %x, *BufferLength - %x\n", 117 SetupPacket->bRequest, 118 *BufferLength); 119 120 FdoExtension = FdoDevice->DeviceExtension; 121 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; 122 Packet = &FdoExtension->MiniPortInterface->Packet; 123 124 Port = SetupPacket->wIndex.W; 125 126 switch (SetupPacket->bRequest) 127 { 128 case USB_REQUEST_GET_STATUS: 129 { 130 if (!Buffer) 131 { 132 return RHStatus; 133 } 134 135 *(PULONG)Buffer = 0; 136 137 if (SetupPacket->bmRequestType.Recipient == BMREQUEST_TO_OTHER) 138 { 139 ASSERT(*BufferLength >= 4); 140 141 if (Port > PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts || 142 Port <= 0 || 143 SetupPacket->wLength < 4) 144 { 145 return RHStatus; 146 } 147 148 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 149 150 MPStatus = Packet->RH_GetPortStatus(FdoExtension->MiniPortExt, 151 SetupPacket->wIndex.W, 152 Buffer); 153 154 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 155 } 156 else 157 { 158 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 159 160 MPStatus = Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, 161 Buffer); 162 163 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 164 } 165 166 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); 167 break; 168 } 169 170 case USB_REQUEST_CLEAR_FEATURE: 171 Feature = SetupPacket->wValue.W; 172 173 if ((SetupPacket->bmRequestType.Recipient) != USBPORT_RECIPIENT_PORT) 174 { 175 if (Feature == FEATURE_C_HUB_LOCAL_POWER) 176 { 177 RHStatus = RH_STATUS_SUCCESS; 178 return RHStatus; 179 } 180 181 if (Feature == FEATURE_C_HUB_OVER_CURRENT) 182 { 183 MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt, 184 0); 185 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); 186 return RHStatus; 187 } 188 189 DbgBreakPoint(); 190 return RHStatus; 191 } 192 193 switch (Feature) 194 { 195 case FEATURE_PORT_ENABLE: 196 MPStatus = Packet->RH_ClearFeaturePortEnable(FdoExtension->MiniPortExt, 197 Port); 198 break; 199 200 case FEATURE_PORT_SUSPEND: 201 MPStatus = Packet->RH_ClearFeaturePortSuspend(FdoExtension->MiniPortExt, 202 Port); 203 break; 204 205 case FEATURE_PORT_POWER: 206 MPStatus = Packet->RH_ClearFeaturePortPower(FdoExtension->MiniPortExt, 207 Port); 208 break; 209 210 case FEATURE_C_PORT_CONNECTION: 211 MPStatus = Packet->RH_ClearFeaturePortConnectChange(FdoExtension->MiniPortExt, 212 Port); 213 break; 214 215 case FEATURE_C_PORT_ENABLE: 216 MPStatus = Packet->RH_ClearFeaturePortEnableChange(FdoExtension->MiniPortExt, 217 Port); 218 break; 219 220 case FEATURE_C_PORT_SUSPEND: 221 MPStatus = Packet->RH_ClearFeaturePortSuspendChange(FdoExtension->MiniPortExt, 222 Port); 223 break; 224 225 case FEATURE_C_PORT_OVER_CURRENT: 226 MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt, 227 Port); 228 break; 229 230 case FEATURE_C_PORT_RESET: 231 MPStatus = Packet->RH_ClearFeaturePortResetChange(FdoExtension->MiniPortExt, 232 Port); 233 break; 234 235 default: 236 DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n", 237 Feature); 238 return RHStatus; 239 } 240 241 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); 242 break; 243 244 case USB_REQUEST_SET_FEATURE: 245 if (SetupPacket->bmRequestType.Recipient != USBPORT_RECIPIENT_PORT) 246 { 247 return RHStatus; 248 } 249 250 Feature = SetupPacket->wValue.W; 251 252 switch (Feature) 253 { 254 case FEATURE_PORT_ENABLE: 255 MPStatus = Packet->RH_SetFeaturePortEnable(FdoExtension->MiniPortExt, 256 Port); 257 break; 258 259 case FEATURE_PORT_SUSPEND: 260 MPStatus = Packet->RH_SetFeaturePortSuspend(FdoExtension->MiniPortExt, 261 Port); 262 break; 263 264 case FEATURE_PORT_RESET: 265 MPStatus = Packet->RH_SetFeaturePortReset(FdoExtension->MiniPortExt, 266 Port); 267 break; 268 269 case FEATURE_PORT_POWER: 270 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 271 { 272 MPStatus = USBPORT_RH_SetFeatureUSB2PortPower(FdoDevice, Port); 273 } 274 else 275 { 276 MPStatus = Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, 277 Port); 278 } 279 280 break; 281 282 default: 283 DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n", 284 Feature); 285 return RHStatus; 286 } 287 288 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); 289 break; 290 291 case USB_REQUEST_GET_DESCRIPTOR: 292 if (Buffer && 293 SetupPacket->wValue.W == 0 && 294 SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) 295 { 296 SIZE_T DescriptorLength; 297 298 DescriptorLength = PdoExtension->RootHubDescriptors->Descriptor.bDescriptorLength; 299 300 if (*BufferLength < DescriptorLength) 301 DescriptorLength = *BufferLength; 302 303 RtlCopyMemory(Buffer, 304 &PdoExtension->RootHubDescriptors->Descriptor, 305 DescriptorLength); 306 307 *BufferLength = DescriptorLength; 308 RHStatus = RH_STATUS_SUCCESS; 309 } 310 311 break; 312 313 default: 314 DPRINT1("USBPORT_RootHubClassCommand: Not supported USB request - %x\n", 315 SetupPacket->bRequest); 316 //USB_REQUEST_SET_ADDRESS 0x05 317 //USB_REQUEST_SET_DESCRIPTOR 0x07 318 //USB_REQUEST_GET_CONFIGURATION 0x08 319 //USB_REQUEST_SET_CONFIGURATION 0x09 320 //USB_REQUEST_GET_INTERFACE 0x0A 321 //USB_REQUEST_SET_INTERFACE 0x0B 322 //USB_REQUEST_SYNC_FRAME 0x0C 323 break; 324 } 325 326 return RHStatus; 327 } 328 329 RHSTATUS 330 NTAPI 331 USBPORT_RootHubStandardCommand(IN PDEVICE_OBJECT FdoDevice, 332 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, 333 IN PVOID Buffer, 334 IN OUT PULONG TransferLength) 335 { 336 PUSBPORT_DEVICE_EXTENSION FdoExtension; 337 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 338 PUSBPORT_REGISTRATION_PACKET Packet; 339 SIZE_T Length; 340 PVOID Descriptor; 341 SIZE_T DescriptorLength; 342 MPSTATUS MPStatus; 343 RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL; 344 KIRQL OldIrql; 345 346 DPRINT("USBPORT_RootHubStandardCommand: USB command - %x, TransferLength - %p\n", 347 SetupPacket->bRequest, 348 TransferLength); 349 350 FdoExtension = FdoDevice->DeviceExtension; 351 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; 352 Packet = &FdoExtension->MiniPortInterface->Packet; 353 354 switch (SetupPacket->bRequest) 355 { 356 case USB_REQUEST_GET_DESCRIPTOR: 357 if (SetupPacket->wValue.LowByte || 358 !(SetupPacket->bmRequestType.Dir)) 359 { 360 return RHStatus; 361 } 362 363 switch (SetupPacket->wValue.HiByte) 364 { 365 case USB_DEVICE_DESCRIPTOR_TYPE: 366 Descriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor; 367 DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR); 368 break; 369 370 case USB_CONFIGURATION_DESCRIPTOR_TYPE: 371 Descriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor; 372 DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 373 sizeof(USB_INTERFACE_DESCRIPTOR) + 374 sizeof(USB_ENDPOINT_DESCRIPTOR); 375 break; 376 377 default: 378 DPRINT1("USBPORT_RootHubStandardCommand: Not supported Descriptor Type - %x\n", 379 SetupPacket->wValue.HiByte); 380 return RHStatus; 381 } 382 383 if (!Descriptor) 384 { 385 return RHStatus; 386 } 387 388 if (*TransferLength >= DescriptorLength) 389 Length = DescriptorLength; 390 else 391 Length = *TransferLength; 392 393 RtlCopyMemory(Buffer, Descriptor, Length); 394 *TransferLength = Length; 395 396 RHStatus = RH_STATUS_SUCCESS; 397 break; 398 399 case USB_REQUEST_GET_STATUS: 400 if (!SetupPacket->wValue.W && 401 SetupPacket->wLength == sizeof(USHORT) && 402 !SetupPacket->wIndex.W && 403 SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) 404 { 405 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 406 407 MPStatus = Packet->RH_GetStatus(FdoExtension->MiniPortExt, 408 Buffer); 409 410 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 411 412 *TransferLength = sizeof(USHORT); 413 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); 414 } 415 416 break; 417 418 case USB_REQUEST_GET_CONFIGURATION: 419 if (SetupPacket->wValue.W || 420 SetupPacket->wIndex.W || 421 SetupPacket->wLength != 1 || 422 SetupPacket->bmRequestType.Dir == BMREQUEST_HOST_TO_DEVICE) 423 { 424 return RHStatus; 425 } 426 427 Length = 0; 428 429 if (*TransferLength >= 1) 430 { 431 Length = 1; 432 RtlCopyMemory(Buffer, &PdoExtension->ConfigurationValue, Length); 433 } 434 435 *TransferLength = Length; 436 437 RHStatus = RH_STATUS_SUCCESS; 438 break; 439 440 case USB_REQUEST_SET_CONFIGURATION: 441 if (!SetupPacket->wIndex.W && 442 !SetupPacket->wLength && 443 !(SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)) 444 { 445 if (SetupPacket->wValue.W == 0 || 446 SetupPacket->wValue.W == 447 PdoExtension->RootHubDescriptors->ConfigDescriptor.bConfigurationValue) 448 { 449 PdoExtension->ConfigurationValue = SetupPacket->wValue.LowByte; 450 RHStatus = RH_STATUS_SUCCESS; 451 } 452 } 453 454 break; 455 456 case USB_REQUEST_SET_ADDRESS: 457 if (!SetupPacket->wIndex.W && 458 !SetupPacket->wLength && 459 !(SetupPacket->bmRequestType.Dir)) 460 { 461 PdoExtension->DeviceHandle.DeviceAddress = SetupPacket->wValue.LowByte; 462 RHStatus = RH_STATUS_SUCCESS; 463 break; 464 } 465 466 break; 467 468 default: 469 DPRINT1("USBPORT_RootHubStandardCommand: Not supported USB request - %x\n", 470 SetupPacket->bRequest); 471 //USB_REQUEST_CLEAR_FEATURE 0x01 472 //USB_REQUEST_SET_FEATURE 0x03 473 //USB_REQUEST_SET_DESCRIPTOR 0x07 474 //USB_REQUEST_GET_INTERFACE 0x0A 475 //USB_REQUEST_SET_INTERFACE 0x0B 476 //USB_REQUEST_SYNC_FRAME 0x0C 477 break; 478 } 479 480 return RHStatus; 481 } 482 483 RHSTATUS 484 NTAPI 485 USBPORT_RootHubEndpoint0(IN PUSBPORT_TRANSFER Transfer) 486 { 487 PDEVICE_OBJECT FdoDevice; 488 ULONG TransferLength; 489 PVOID Buffer; 490 PURB Urb; 491 PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket; 492 UCHAR Type; 493 RHSTATUS RHStatus; 494 495 DPRINT("USBPORT_RootHubEndpoint0: Transfer - %p\n", Transfer); 496 497 TransferLength = Transfer->TransferParameters.TransferBufferLength; 498 Urb = Transfer->Urb; 499 FdoDevice = Transfer->Endpoint->FdoDevice; 500 501 if (TransferLength > 0) 502 Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa; 503 else 504 Buffer = NULL; 505 506 SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket; 507 508 Type = SetupPacket->bmRequestType.Type; 509 510 if (Type == BMREQUEST_STANDARD) 511 { 512 RHStatus = USBPORT_RootHubStandardCommand(FdoDevice, 513 SetupPacket, 514 Buffer, 515 &TransferLength); 516 } 517 else if (Type == BMREQUEST_CLASS) 518 { 519 RHStatus = USBPORT_RootHubClassCommand(FdoDevice, 520 SetupPacket, 521 Buffer, 522 &TransferLength); 523 } 524 else 525 { 526 return RH_STATUS_UNSUCCESSFUL; 527 } 528 529 if (RHStatus == RH_STATUS_SUCCESS) 530 Transfer->CompletedTransferLen = TransferLength; 531 532 return RHStatus; 533 } 534 535 RHSTATUS 536 NTAPI 537 USBPORT_RootHubSCE(IN PUSBPORT_TRANSFER Transfer) 538 { 539 PUSBPORT_ENDPOINT Endpoint; 540 PUSBPORT_DEVICE_EXTENSION FdoExtension; 541 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 542 PUSBPORT_REGISTRATION_PACKET Packet; 543 ULONG TransferLength; 544 USB_PORT_STATUS_AND_CHANGE PortStatus; 545 USB_HUB_STATUS_AND_CHANGE HubStatus; 546 PVOID Buffer; 547 PULONG AddressBitMap; 548 ULONG Port; 549 PURB Urb; 550 RHSTATUS RHStatus = RH_STATUS_NO_CHANGES; 551 PUSB_HUB_DESCRIPTOR HubDescriptor; 552 UCHAR NumberOfPorts; 553 554 DPRINT("USBPORT_RootHubSCE: Transfer - %p\n", Transfer); 555 556 Endpoint = Transfer->Endpoint; 557 558 FdoExtension = Endpoint->FdoDevice->DeviceExtension; 559 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; 560 Packet = &FdoExtension->MiniPortInterface->Packet; 561 562 HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor; 563 NumberOfPorts = HubDescriptor->bNumberOfPorts; 564 565 PortStatus.AsUlong32 = 0; 566 HubStatus.AsUlong32 = 0; 567 568 Urb = Transfer->Urb; 569 TransferLength = Transfer->TransferParameters.TransferBufferLength; 570 571 if (TransferLength) 572 { 573 Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa; 574 } 575 else 576 { 577 Buffer = NULL; 578 } 579 580 /* Check parameters */ 581 582 if (!Buffer) 583 { 584 /* Not valid parameter */ 585 DPRINT1("USBPORT_RootHubSCE: Error! Buffer is NULL\n"); 586 return RH_STATUS_UNSUCCESSFUL; 587 } 588 589 if ((TransferLength < (NumberOfPorts / 8 + 1))) 590 { 591 /* Not valid parameters */ 592 DPRINT1("USBPORT_RootHubSCE: Error! TransferLength - %x, NumberOfPorts - %x\n", 593 TransferLength, 594 NumberOfPorts); 595 596 return RH_STATUS_UNSUCCESSFUL; 597 } 598 599 RtlZeroMemory(Buffer, TransferLength); 600 601 AddressBitMap = Buffer; 602 603 /* Scan all the ports for changes */ 604 for (Port = 1; Port <= NumberOfPorts; Port++) 605 { 606 DPRINT_CORE("USBPORT_RootHubSCE: Port - %p\n", Port); 607 608 /* Request the port status from miniport */ 609 if (Packet->RH_GetPortStatus(FdoExtension->MiniPortExt, 610 Port, 611 &PortStatus)) 612 { 613 /* Miniport returned an error */ 614 DPRINT1("USBPORT_RootHubSCE: RH_GetPortStatus failed\n"); 615 return RH_STATUS_UNSUCCESSFUL; 616 } 617 618 if (PortStatus.PortChange.Usb20PortChange.ConnectStatusChange || 619 PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange || 620 PortStatus.PortChange.Usb20PortChange.SuspendChange || 621 PortStatus.PortChange.Usb20PortChange.OverCurrentIndicatorChange || 622 PortStatus.PortChange.Usb20PortChange.ResetChange) 623 { 624 /* At the port status there is a change */ 625 AddressBitMap[Port >> 5] |= 1 << (Port & 0x1F); 626 RHStatus = RH_STATUS_SUCCESS; 627 } 628 } 629 630 /* Request the hub status from miniport */ 631 if (!Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, &HubStatus)) 632 { 633 if (HubStatus.HubChange.LocalPowerChange == 1 || 634 HubStatus.HubChange.OverCurrentChange == 1) 635 { 636 /* At the hub status there is a change */ 637 AddressBitMap[0] |= 1; 638 RHStatus = RH_STATUS_SUCCESS; 639 } 640 641 if (RHStatus == RH_STATUS_SUCCESS) 642 { 643 /* Done */ 644 Urb->UrbControlTransfer.TransferBufferLength = TransferLength; 645 return RH_STATUS_SUCCESS; 646 } 647 648 if (RHStatus == RH_STATUS_NO_CHANGES) 649 { 650 /* No changes. Enable IRQs for miniport root hub */ 651 Packet->RH_EnableIrq(FdoExtension->MiniPortExt); 652 } 653 654 return RHStatus; 655 } 656 657 /* Miniport returned an error */ 658 DPRINT1("USBPORT_RootHubSCE: RH_GetHubStatus failed\n"); 659 return RH_STATUS_UNSUCCESSFUL; 660 } 661 662 VOID 663 NTAPI 664 USBPORT_RootHubEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint) 665 { 666 PDEVICE_OBJECT FdoDevice; 667 PUSBPORT_DEVICE_EXTENSION FdoExtension; 668 PUSBPORT_REGISTRATION_PACKET Packet; 669 PUSBPORT_TRANSFER Transfer; 670 RHSTATUS RHStatus; 671 USBD_STATUS USBDStatus; 672 KIRQL OldIrql; 673 674 DPRINT_CORE("USBPORT_RootHubEndpointWorker: Endpoint - %p\n", Endpoint); 675 676 FdoDevice = Endpoint->FdoDevice; 677 FdoExtension = FdoDevice->DeviceExtension; 678 Packet = &FdoExtension->MiniPortInterface->Packet; 679 680 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 681 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)) 682 { 683 Packet->CheckController(FdoExtension->MiniPortExt); 684 } 685 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 686 687 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 688 689 Transfer = CONTAINING_RECORD(Endpoint->TransferList.Flink, 690 USBPORT_TRANSFER, 691 TransferLink); 692 693 if (IsListEmpty(&Endpoint->TransferList) || 694 Endpoint->TransferList.Flink == NULL || 695 !Transfer) 696 { 697 if (Endpoint->StateLast == USBPORT_ENDPOINT_REMOVE) 698 { 699 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList, 700 &Endpoint->CloseLink, 701 &FdoExtension->EndpointClosedSpinLock); 702 } 703 704 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 705 706 USBPORT_FlushCancelList(Endpoint); 707 return; 708 } 709 710 if (Transfer->Flags & (TRANSFER_FLAG_ABORTED | TRANSFER_FLAG_CANCELED)) 711 { 712 RemoveEntryList(&Transfer->TransferLink); 713 InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink); 714 715 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 716 USBPORT_FlushCancelList(Endpoint); 717 return; 718 } 719 720 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 721 722 if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 723 RHStatus = USBPORT_RootHubEndpoint0(Transfer); 724 else 725 RHStatus = USBPORT_RootHubSCE(Transfer); 726 727 if (RHStatus != RH_STATUS_NO_CHANGES) 728 { 729 if (RHStatus == RH_STATUS_SUCCESS) 730 USBDStatus = USBD_STATUS_SUCCESS; 731 else 732 USBDStatus = USBD_STATUS_STALL_PID; 733 734 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 735 USBPORT_QueueDoneTransfer(Transfer, USBDStatus); 736 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 737 738 USBPORT_FlushCancelList(Endpoint); 739 return; 740 } 741 742 USBPORT_FlushCancelList(Endpoint); 743 } 744 745 NTSTATUS 746 NTAPI 747 USBPORT_RootHubCreateDevice(IN PDEVICE_OBJECT FdoDevice, 748 IN PDEVICE_OBJECT PdoDevice) 749 { 750 PUSBPORT_DEVICE_EXTENSION FdoExtension; 751 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 752 PUSBPORT_REGISTRATION_PACKET Packet; 753 PUSBPORT_DEVICE_HANDLE DeviceHandle; 754 USBPORT_ROOT_HUB_DATA RootHubData; 755 ULONG NumMaskByte; 756 ULONG DescriptorsLength; 757 PUSBPORT_RH_DESCRIPTORS Descriptors; 758 PUSB_DEVICE_DESCRIPTOR RH_DeviceDescriptor; 759 PUSB_CONFIGURATION_DESCRIPTOR RH_ConfigurationDescriptor; 760 PUSB_INTERFACE_DESCRIPTOR RH_InterfaceDescriptor; 761 PUSB_ENDPOINT_DESCRIPTOR RH_EndPointDescriptor; 762 PUSB_HUB_DESCRIPTOR RH_HubDescriptor; 763 ULONG ix; 764 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; 765 NTSTATUS Status; 766 767 DPRINT("USBPORT_RootHubCreateDevice: FdoDevice - %p, PdoDevice - %p\n", 768 FdoDevice, 769 PdoDevice); 770 771 FdoExtension = FdoDevice->DeviceExtension; 772 PdoExtension = PdoDevice->DeviceExtension; 773 Packet = &FdoExtension->MiniPortInterface->Packet; 774 775 DeviceHandle = &PdoExtension->DeviceHandle; 776 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle); 777 778 InitializeListHead(&DeviceHandle->PipeHandleList); 779 780 DeviceHandle->IsRootHub = TRUE; 781 DeviceHandle->DeviceSpeed = UsbFullSpeed; 782 DeviceHandle->Flags = DEVICE_HANDLE_FLAG_ROOTHUB; 783 784 RtlZeroMemory(&RootHubData, sizeof(RootHubData)); 785 786 Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, &RootHubData); 787 788 ASSERT(RootHubData.NumberOfPorts != 0); 789 NumMaskByte = (RootHubData.NumberOfPorts - 1) / 8 + 1; 790 791 DescriptorsLength = sizeof(USB_DEVICE_DESCRIPTOR) + 792 sizeof(USB_CONFIGURATION_DESCRIPTOR) + 793 sizeof(USB_INTERFACE_DESCRIPTOR) + 794 sizeof(USB_ENDPOINT_DESCRIPTOR) + 795 (sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte); 796 797 Descriptors = ExAllocatePoolWithTag(NonPagedPool, 798 DescriptorsLength, 799 USB_PORT_TAG); 800 801 if (Descriptors) 802 { 803 RtlZeroMemory(Descriptors, DescriptorsLength); 804 805 PdoExtension->RootHubDescriptors = Descriptors; 806 807 RH_DeviceDescriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor; 808 809 RH_DeviceDescriptor->bLength = sizeof(USB_DEVICE_DESCRIPTOR); 810 RH_DeviceDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; 811 RH_DeviceDescriptor->bcdUSB = 0x100; 812 RH_DeviceDescriptor->bDeviceClass = USB_DEVICE_CLASS_HUB; 813 RH_DeviceDescriptor->bDeviceSubClass = 0x01; 814 RH_DeviceDescriptor->bDeviceProtocol = 0x00; 815 RH_DeviceDescriptor->bMaxPacketSize0 = 0x08; 816 RH_DeviceDescriptor->idVendor = FdoExtension->VendorID; 817 RH_DeviceDescriptor->idProduct = FdoExtension->DeviceID; 818 RH_DeviceDescriptor->bcdDevice = FdoExtension->RevisionID; 819 RH_DeviceDescriptor->iManufacturer = 0x00; 820 RH_DeviceDescriptor->iProduct = 0x00; 821 RH_DeviceDescriptor->iSerialNumber = 0x00; 822 RH_DeviceDescriptor->bNumConfigurations = 0x01; 823 824 RH_ConfigurationDescriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor; 825 826 RH_ConfigurationDescriptor->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR); 827 RH_ConfigurationDescriptor->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE; 828 829 RH_ConfigurationDescriptor->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 830 sizeof(USB_INTERFACE_DESCRIPTOR) + 831 sizeof(USB_ENDPOINT_DESCRIPTOR); 832 833 RH_ConfigurationDescriptor->bNumInterfaces = 0x01; 834 RH_ConfigurationDescriptor->bConfigurationValue = 0x01; 835 RH_ConfigurationDescriptor->iConfiguration = 0x00; 836 RH_ConfigurationDescriptor->bmAttributes = USB_CONFIG_SELF_POWERED; 837 RH_ConfigurationDescriptor->MaxPower = 0x00; 838 839 RH_InterfaceDescriptor = &PdoExtension->RootHubDescriptors->InterfaceDescriptor; 840 841 RH_InterfaceDescriptor->bLength = sizeof(USB_INTERFACE_DESCRIPTOR); 842 RH_InterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE; 843 RH_InterfaceDescriptor->bInterfaceNumber = 0x00; 844 RH_InterfaceDescriptor->bAlternateSetting = 0x00; 845 RH_InterfaceDescriptor->bNumEndpoints = 0x01; 846 RH_InterfaceDescriptor->bInterfaceClass = USB_DEVICE_CLASS_HUB; 847 RH_InterfaceDescriptor->bInterfaceSubClass = 0x01; 848 RH_InterfaceDescriptor->bInterfaceProtocol = 0x00; 849 RH_InterfaceDescriptor->iInterface = 0x00; 850 851 RH_EndPointDescriptor = &PdoExtension->RootHubDescriptors->EndPointDescriptor; 852 853 RH_EndPointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR); 854 RH_EndPointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE; 855 RH_EndPointDescriptor->bEndpointAddress = 0x81; 856 RH_EndPointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT; // SCE endpoint 857 RH_EndPointDescriptor->wMaxPacketSize = 0x0008; 858 RH_EndPointDescriptor->bInterval = 0x0C; // 12 msec 859 860 RH_HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor; 861 862 RH_HubDescriptor->bDescriptorLength = FIELD_OFFSET(USB_HUB_DESCRIPTOR, bRemoveAndPowerMask) + 2 * NumMaskByte; 863 864 if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_OHCI || 865 Packet->MiniPortVersion == USB_MINIPORT_VERSION_UHCI || 866 Packet->MiniPortVersion == USB_MINIPORT_VERSION_EHCI) 867 { 868 RH_HubDescriptor->bDescriptorType = USB_20_HUB_DESCRIPTOR_TYPE; 869 } 870 else if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_XHCI) 871 { 872 RH_HubDescriptor->bDescriptorType = USB_30_HUB_DESCRIPTOR_TYPE; 873 } 874 else 875 { 876 DPRINT1("USBPORT_RootHubCreateDevice: Unknown MiniPortVersion - %x\n", 877 Packet->MiniPortVersion); 878 879 DbgBreakPoint(); 880 } 881 882 RH_HubDescriptor->bNumberOfPorts = RootHubData.NumberOfPorts; 883 RH_HubDescriptor->wHubCharacteristics = RootHubData.HubCharacteristics.AsUSHORT; 884 RH_HubDescriptor->bPowerOnToPowerGood = RootHubData.PowerOnToPowerGood; 885 RH_HubDescriptor->bHubControlCurrent = RootHubData.HubControlCurrent; 886 887 for (ix = 0; ix < NumMaskByte; ix += 2) 888 { 889 RH_HubDescriptor->bRemoveAndPowerMask[ix] = 0; 890 RH_HubDescriptor->bRemoveAndPowerMask[ix + 1] = -1; 891 } 892 893 EndpointDescriptor = &DeviceHandle->PipeHandle.EndpointDescriptor; 894 895 EndpointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR); 896 EndpointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE; 897 EndpointDescriptor->bEndpointAddress = 0x00; 898 EndpointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_CONTROL; 899 EndpointDescriptor->wMaxPacketSize = 0x0040; 900 EndpointDescriptor->bInterval = 0x00; 901 902 Status = USBPORT_OpenPipe(FdoDevice, 903 DeviceHandle, 904 &DeviceHandle->PipeHandle, 905 NULL); 906 } 907 else 908 { 909 Status = STATUS_INSUFFICIENT_RESOURCES; 910 } 911 912 return Status; 913 } 914 915 ULONG 916 NTAPI 917 USBPORT_InvalidateRootHub(PVOID MiniPortExtension) 918 { 919 PUSBPORT_DEVICE_EXTENSION FdoExtension; 920 PDEVICE_OBJECT FdoDevice; 921 PDEVICE_OBJECT PdoDevice; 922 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 923 PUSBPORT_ENDPOINT Endpoint = NULL; 924 925 DPRINT("USBPORT_InvalidateRootHub ... \n"); 926 927 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension - 928 sizeof(USBPORT_DEVICE_EXTENSION)); 929 930 FdoDevice = FdoExtension->CommonExtension.SelfDevice; 931 932 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND && 933 FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT && 934 FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED && 935 FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE) 936 { 937 USBPORT_HcQueueWakeDpc(FdoDevice); 938 return 0; 939 } 940 941 FdoExtension->MiniPortInterface->Packet.RH_DisableIrq(FdoExtension->MiniPortExt); 942 943 PdoDevice = FdoExtension->RootHubPdo; 944 945 if (PdoDevice) 946 { 947 PdoExtension = PdoDevice->DeviceExtension; 948 Endpoint = PdoExtension->Endpoint; 949 950 if (Endpoint) 951 { 952 USBPORT_InvalidateEndpointHandler(FdoDevice, 953 PdoExtension->Endpoint, 954 INVALIDATE_ENDPOINT_WORKER_THREAD); 955 } 956 } 957 958 return 0; 959 } 960 961 VOID 962 NTAPI 963 USBPORT_RootHubPowerAndChirpAllCcPorts(IN PDEVICE_OBJECT FdoDevice) 964 { 965 PUSBPORT_DEVICE_EXTENSION FdoExtension; 966 PUSBPORT_REGISTRATION_PACKET Packet; 967 USBPORT_ROOT_HUB_DATA RootHubData; 968 ULONG Port; 969 PDEVICE_RELATIONS CompanionControllersList; 970 PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension; 971 PUSBPORT_REGISTRATION_PACKET CompanionPacket; 972 ULONG CompanionPorts; 973 ULONG NumController; 974 PDEVICE_OBJECT * Entry; 975 ULONG NumPorts; 976 977 DPRINT("USBPORT_RootHub_PowerAndChirpAllCcPorts: FdoDevice - %p\n", 978 FdoDevice); 979 980 FdoExtension = FdoDevice->DeviceExtension; 981 982 Packet = &FdoExtension->MiniPortInterface->Packet; 983 984 RtlZeroMemory(&RootHubData, sizeof(RootHubData)); 985 986 Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, 987 &RootHubData); 988 989 NumPorts = RootHubData.NumberOfPorts; 990 991 for (Port = 1; Port <= NumPorts; ++Port) 992 { 993 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); 994 } 995 996 USBPORT_Wait(FdoDevice, 10); 997 998 CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice, 999 FALSE, 1000 TRUE); 1001 1002 if (CompanionControllersList) 1003 { 1004 Entry = &CompanionControllersList->Objects[0]; 1005 1006 for (NumController = 0; 1007 NumController < CompanionControllersList->Count; 1008 NumController++) 1009 { 1010 CompanionPacket = &FdoExtension->MiniPortInterface->Packet; 1011 1012 CompanionFdoExtension = (*Entry)->DeviceExtension; 1013 1014 CompanionPacket->RH_GetRootHubData(CompanionFdoExtension->MiniPortExt, 1015 &RootHubData); 1016 1017 CompanionPorts = RootHubData.NumberOfPorts; 1018 1019 for (Port = 1; Port <= CompanionPorts; ++Port) 1020 { 1021 CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt, 1022 Port); 1023 } 1024 1025 ++Entry; 1026 } 1027 1028 ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG); 1029 } 1030 1031 USBPORT_Wait(FdoDevice, 100); 1032 1033 for (Port = 1; Port <= NumPorts; ++Port) 1034 { 1035 if (FdoExtension->MiniPortInterface->Version < 200) 1036 { 1037 break; 1038 } 1039 1040 InterlockedIncrement((PLONG)&FdoExtension->ChirpRootPortLock); 1041 Packet->RH_ChirpRootPort(FdoExtension->MiniPortExt, Port); 1042 InterlockedDecrement((PLONG)&FdoExtension->ChirpRootPortLock); 1043 } 1044 } 1045