1 /* 2 * PROJECT: ReactOS USB Port Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBPort endpoint 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 ULONG 17 NTAPI 18 USBPORT_CalculateUsbBandwidth(IN PDEVICE_OBJECT FdoDevice, 19 IN PUSBPORT_ENDPOINT Endpoint) 20 { 21 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 22 ULONG Bandwidth; 23 ULONG Overhead; 24 25 DPRINT("USBPORT_CalculateUsbBandwidth ... \n"); 26 27 EndpointProperties = &Endpoint->EndpointProperties; 28 29 switch (EndpointProperties->TransferType) 30 { 31 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 32 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD; 33 break; 34 35 case USBPORT_TRANSFER_TYPE_INTERRUPT: 36 Overhead = USB2_FS_INTERRUPT_OVERHEAD; 37 break; 38 39 default: //USBPORT_TRANSFER_TYPE_CONTROL or USBPORT_TRANSFER_TYPE_BULK 40 Overhead = 0; 41 break; 42 } 43 44 if (Overhead == 0) 45 { 46 Bandwidth = 0; 47 } 48 else 49 { 50 Bandwidth = (EndpointProperties->TotalMaxPacketSize + Overhead) * USB2_BIT_STUFFING_OVERHEAD; 51 } 52 53 if (EndpointProperties->DeviceSpeed == UsbLowSpeed) 54 { 55 Bandwidth *= 8; 56 } 57 58 return Bandwidth; 59 } 60 61 BOOLEAN 62 NTAPI 63 USBPORT_AllocateBandwidth(IN PDEVICE_OBJECT FdoDevice, 64 IN PUSBPORT_ENDPOINT Endpoint) 65 { 66 PUSBPORT_DEVICE_EXTENSION FdoExtension; 67 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 68 ULONG TransferType; 69 ULONG TotalBusBandwidth; 70 ULONG EndpointBandwidth; 71 ULONG MinBandwidth; 72 PULONG Bandwidth; 73 ULONG MaxBandwidth = 0; 74 ULONG ix; 75 ULONG Offset; 76 LONG ScheduleOffset = -1; 77 ULONG Period; 78 ULONG Factor; 79 UCHAR Bit; 80 81 DPRINT("USBPORT_AllocateBandwidth: FdoDevice - %p, Endpoint - %p\n", 82 FdoDevice, 83 Endpoint); 84 85 FdoExtension = FdoDevice->DeviceExtension; 86 EndpointProperties = &Endpoint->EndpointProperties; 87 TransferType = EndpointProperties->TransferType; 88 89 if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 90 TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 91 Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) 92 { 93 EndpointProperties->ScheduleOffset = 0; 94 return TRUE; 95 } 96 97 TotalBusBandwidth = FdoExtension->TotalBusBandwidth; 98 EndpointBandwidth = EndpointProperties->UsbBandwidth; 99 100 Period = EndpointProperties->Period; 101 ASSERT(Period != 0); 102 Factor = USB2_FRAMES / Period; 103 104 for (Offset = 0; Offset < Period; Offset++) 105 { 106 MinBandwidth = TotalBusBandwidth; 107 Bandwidth = &FdoExtension->Bandwidth[Offset * Factor]; 108 109 for (ix = 1; *Bandwidth >= EndpointBandwidth; ix++) 110 { 111 MinBandwidth = min(MinBandwidth, *Bandwidth); 112 113 Bandwidth++; 114 115 if (Factor <= ix) 116 { 117 if (MinBandwidth > MaxBandwidth) 118 { 119 MaxBandwidth = MinBandwidth; 120 ScheduleOffset = Offset; 121 122 DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n", 123 ScheduleOffset); 124 } 125 126 break; 127 } 128 } 129 } 130 131 DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n", ScheduleOffset); 132 133 if (ScheduleOffset != -1) 134 { 135 EndpointProperties->ScheduleOffset = ScheduleOffset; 136 137 Bandwidth = &FdoExtension->Bandwidth[ScheduleOffset * Factor]; 138 139 for (Factor = USB2_FRAMES / Period; Factor; Factor--) 140 { 141 FdoExtension->Bandwidth[ScheduleOffset * Factor] -= EndpointBandwidth; 142 } 143 144 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 145 { 146 for (Bit = 0x80; Bit != 0; Bit >>= 1) 147 { 148 if ((Period & Bit) != 0) 149 { 150 Period = Bit; 151 break; 152 } 153 } 154 155 DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedInterrupt_XXms\n"); 156 } 157 else 158 { 159 DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedIso\n"); 160 } 161 } 162 163 DPRINT("USBPORT_AllocateBandwidth: FIXME USBPORT_UpdateAllocatedBw\n"); 164 165 DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n", ScheduleOffset); 166 return ScheduleOffset != -1; 167 } 168 169 VOID 170 NTAPI 171 USBPORT_FreeBandwidth(IN PDEVICE_OBJECT FdoDevice, 172 IN PUSBPORT_ENDPOINT Endpoint) 173 { 174 PUSBPORT_DEVICE_EXTENSION FdoExtension; 175 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 176 ULONG TransferType; 177 ULONG Offset; 178 ULONG EndpointBandwidth; 179 ULONG Period; 180 ULONG Factor; 181 UCHAR Bit; 182 183 DPRINT("USBPORT_FreeBandwidth: FdoDevice - %p, Endpoint - %p\n", 184 FdoDevice, 185 Endpoint); 186 187 FdoExtension = FdoDevice->DeviceExtension; 188 189 EndpointProperties = &Endpoint->EndpointProperties; 190 TransferType = EndpointProperties->TransferType; 191 192 if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 193 TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 194 (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)) 195 { 196 return; 197 } 198 199 Offset = Endpoint->EndpointProperties.ScheduleOffset; 200 EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth; 201 202 Period = Endpoint->EndpointProperties.Period; 203 ASSERT(Period != 0); 204 205 for (Factor = USB2_FRAMES / Period; Factor; Factor--) 206 { 207 FdoExtension->Bandwidth[Offset * Factor] += EndpointBandwidth; 208 } 209 210 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 211 { 212 for (Bit = 0x80; Bit != 0; Bit >>= 1) 213 { 214 if ((Period & Bit) != 0) 215 { 216 Period = Bit; 217 break; 218 } 219 } 220 221 ASSERT(Period != 0); 222 223 DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedInterrupt_XXms\n"); 224 } 225 else 226 { 227 DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedIso\n"); 228 } 229 230 DPRINT1("USBPORT_FreeBandwidth: FIXME USBPORT_UpdateAllocatedBw\n"); 231 } 232 233 UCHAR 234 NTAPI 235 USBPORT_NormalizeHsInterval(UCHAR Interval) 236 { 237 UCHAR interval; 238 239 DPRINT("USBPORT_NormalizeHsInterval: Interval - %x\n", Interval); 240 241 interval = Interval; 242 243 if (Interval) 244 interval = Interval - 1; 245 246 if (interval > 5) 247 interval = 5; 248 249 return 1 << interval; 250 } 251 252 BOOLEAN 253 NTAPI 254 USBPORT_EndpointHasQueuedTransfers(IN PDEVICE_OBJECT FdoDevice, 255 IN PUSBPORT_ENDPOINT Endpoint, 256 IN PULONG TransferCount) 257 { 258 PLIST_ENTRY Entry; 259 PUSBPORT_TRANSFER Transfer; 260 BOOLEAN Result = FALSE; 261 262 DPRINT_CORE("USBPORT_EndpointHasQueuedTransfers: ... \n"); 263 264 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 265 266 if (!IsListEmpty(&Endpoint->PendingTransferList)) 267 Result = TRUE; 268 269 if (!IsListEmpty(&Endpoint->TransferList)) 270 { 271 Result = TRUE; 272 273 if (TransferCount) 274 { 275 *TransferCount = 0; 276 277 for (Entry = Endpoint->TransferList.Flink; 278 Entry && Entry != &Endpoint->TransferList; 279 Entry = Transfer->TransferLink.Flink) 280 { 281 Transfer = CONTAINING_RECORD(Entry, 282 USBPORT_TRANSFER, 283 TransferLink); 284 285 if (Transfer->Flags & TRANSFER_FLAG_SUBMITED) 286 { 287 ++*TransferCount; 288 } 289 } 290 } 291 } 292 293 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 294 295 return Result; 296 } 297 298 VOID 299 NTAPI 300 USBPORT_NukeAllEndpoints(IN PDEVICE_OBJECT FdoDevice) 301 { 302 PUSBPORT_DEVICE_EXTENSION FdoExtension; 303 PLIST_ENTRY EndpointList; 304 PUSBPORT_ENDPOINT Endpoint; 305 KIRQL OldIrql; 306 307 DPRINT("USBPORT_NukeAllEndpoints \n"); 308 309 FdoExtension = FdoDevice->DeviceExtension; 310 311 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 312 313 EndpointList = FdoExtension->EndpointList.Flink; 314 315 while (EndpointList && (EndpointList != &FdoExtension->EndpointList)) 316 { 317 Endpoint = CONTAINING_RECORD(EndpointList, 318 USBPORT_ENDPOINT, 319 EndpointLink); 320 321 if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)) 322 Endpoint->Flags |= ENDPOINT_FLAG_NUKE; 323 324 EndpointList = Endpoint->EndpointLink.Flink; 325 } 326 327 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 328 } 329 330 ULONG 331 NTAPI 332 USBPORT_GetEndpointState(IN PUSBPORT_ENDPOINT Endpoint) 333 { 334 ULONG State; 335 336 //DPRINT("USBPORT_GetEndpointState \n"); 337 338 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 339 340 if (Endpoint->StateLast != Endpoint->StateNext) 341 { 342 State = USBPORT_ENDPOINT_UNKNOWN; 343 } 344 else 345 { 346 State = Endpoint->StateLast; 347 } 348 349 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 350 351 if (State != USBPORT_ENDPOINT_ACTIVE) 352 { 353 DPRINT("USBPORT_GetEndpointState: Endpoint - %p, State - %x\n", 354 Endpoint, 355 State); 356 } 357 358 return State; 359 } 360 361 VOID 362 NTAPI 363 USBPORT_SetEndpointState(IN PUSBPORT_ENDPOINT Endpoint, 364 IN ULONG State) 365 { 366 PDEVICE_OBJECT FdoDevice; 367 PUSBPORT_DEVICE_EXTENSION FdoExtension; 368 PUSBPORT_REGISTRATION_PACKET Packet; 369 KIRQL OldIrql; 370 371 DPRINT("USBPORT_SetEndpointState: Endpoint - %p, State - %x\n", 372 Endpoint, 373 State); 374 375 FdoDevice = Endpoint->FdoDevice; 376 FdoExtension = FdoDevice->DeviceExtension; 377 Packet = &FdoExtension->MiniPortInterface->Packet; 378 379 KeAcquireSpinLock(&Endpoint->StateChangeSpinLock, 380 &Endpoint->EndpointStateOldIrql); 381 382 if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)) 383 { 384 if (Endpoint->Flags & ENDPOINT_FLAG_NUKE) 385 { 386 Endpoint->StateLast = State; 387 Endpoint->StateNext = State; 388 389 KeReleaseSpinLock(&Endpoint->StateChangeSpinLock, 390 Endpoint->EndpointStateOldIrql); 391 392 USBPORT_InvalidateEndpointHandler(FdoDevice, 393 Endpoint, 394 INVALIDATE_ENDPOINT_WORKER_THREAD); 395 return; 396 } 397 398 KeReleaseSpinLock(&Endpoint->StateChangeSpinLock, 399 Endpoint->EndpointStateOldIrql); 400 401 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 402 Packet->SetEndpointState(FdoExtension->MiniPortExt, 403 Endpoint + 1, 404 State); 405 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 406 407 Endpoint->StateNext = State; 408 409 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 410 Endpoint->FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt); 411 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 412 413 ExInterlockedInsertTailList(&FdoExtension->EpStateChangeList, 414 &Endpoint->StateChangeLink, 415 &FdoExtension->EpStateChangeSpinLock); 416 417 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 418 Packet->InterruptNextSOF(FdoExtension->MiniPortExt); 419 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 420 } 421 else 422 { 423 Endpoint->StateLast = State; 424 Endpoint->StateNext = State; 425 426 if (State == USBPORT_ENDPOINT_REMOVE) 427 { 428 KeReleaseSpinLock(&Endpoint->StateChangeSpinLock, 429 Endpoint->EndpointStateOldIrql); 430 431 USBPORT_InvalidateEndpointHandler(FdoDevice, 432 Endpoint, 433 INVALIDATE_ENDPOINT_WORKER_THREAD); 434 return; 435 } 436 437 KeReleaseSpinLock(&Endpoint->StateChangeSpinLock, 438 Endpoint->EndpointStateOldIrql); 439 } 440 } 441 442 VOID 443 NTAPI 444 USBPORT_AddPipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle, 445 IN PUSBPORT_PIPE_HANDLE PipeHandle) 446 { 447 DPRINT("USBPORT_AddPipeHandle: DeviceHandle - %p, PipeHandle - %p\n", 448 DeviceHandle, 449 PipeHandle); 450 451 InsertTailList(&DeviceHandle->PipeHandleList, &PipeHandle->PipeLink); 452 } 453 454 VOID 455 NTAPI 456 USBPORT_RemovePipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle, 457 IN PUSBPORT_PIPE_HANDLE PipeHandle) 458 { 459 DPRINT("USBPORT_RemovePipeHandle: PipeHandle - %p\n", PipeHandle); 460 461 RemoveEntryList(&PipeHandle->PipeLink); 462 463 PipeHandle->PipeLink.Flink = NULL; 464 PipeHandle->PipeLink.Blink = NULL; 465 } 466 467 BOOLEAN 468 NTAPI 469 USBPORT_ValidatePipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle, 470 IN PUSBPORT_PIPE_HANDLE PipeHandle) 471 { 472 PLIST_ENTRY HandleList; 473 PUSBPORT_PIPE_HANDLE CurrentHandle; 474 475 //DPRINT("USBPORT_ValidatePipeHandle: DeviceHandle - %p, PipeHandle - %p\n", 476 // DeviceHandle, 477 // PipeHandle); 478 479 HandleList = DeviceHandle->PipeHandleList.Flink; 480 481 while (HandleList != &DeviceHandle->PipeHandleList) 482 { 483 CurrentHandle = CONTAINING_RECORD(HandleList, 484 USBPORT_PIPE_HANDLE, 485 PipeLink); 486 487 HandleList = HandleList->Flink; 488 489 if (CurrentHandle == PipeHandle) 490 return TRUE; 491 } 492 493 return FALSE; 494 } 495 496 BOOLEAN 497 NTAPI 498 USBPORT_DeleteEndpoint(IN PDEVICE_OBJECT FdoDevice, 499 IN PUSBPORT_ENDPOINT Endpoint) 500 { 501 PUSBPORT_DEVICE_EXTENSION FdoExtension; 502 BOOLEAN Result; 503 KIRQL OldIrql; 504 505 DPRINT1("USBPORT_DeleteEndpoint: Endpoint - %p\n", Endpoint); 506 507 FdoExtension = FdoDevice->DeviceExtension; 508 509 if ((Endpoint->WorkerLink.Flink && Endpoint->WorkerLink.Blink) || 510 Endpoint->LockCounter != -1) 511 { 512 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 513 514 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList, 515 &Endpoint->CloseLink, 516 &FdoExtension->EndpointClosedSpinLock); 517 518 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 519 520 Result = FALSE; 521 } 522 else 523 { 524 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 525 526 RemoveEntryList(&Endpoint->EndpointLink); 527 Endpoint->EndpointLink.Flink = NULL; 528 Endpoint->EndpointLink.Blink = NULL; 529 530 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 531 532 MiniportCloseEndpoint(FdoDevice, Endpoint); 533 534 if (Endpoint->HeaderBuffer) 535 { 536 USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer); 537 } 538 539 ExFreePoolWithTag(Endpoint, USB_PORT_TAG); 540 541 Result = TRUE; 542 } 543 544 return Result; 545 } 546 547 VOID 548 NTAPI 549 MiniportCloseEndpoint(IN PDEVICE_OBJECT FdoDevice, 550 IN PUSBPORT_ENDPOINT Endpoint) 551 { 552 PUSBPORT_DEVICE_EXTENSION FdoExtension; 553 PUSBPORT_REGISTRATION_PACKET Packet; 554 BOOLEAN IsDoDisablePeriodic; 555 ULONG TransferType; 556 KIRQL OldIrql; 557 558 DPRINT("MiniportCloseEndpoint: Endpoint - %p\n", Endpoint); 559 560 FdoExtension = FdoDevice->DeviceExtension; 561 Packet = &FdoExtension->MiniPortInterface->Packet; 562 563 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 564 565 if (Endpoint->Flags & ENDPOINT_FLAG_OPENED) 566 { 567 TransferType = Endpoint->EndpointProperties.TransferType; 568 569 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT || 570 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 571 { 572 --FdoExtension->PeriodicEndpoints; 573 } 574 575 IsDoDisablePeriodic = FdoExtension->PeriodicEndpoints == 0; 576 577 Packet->CloseEndpoint(FdoExtension->MiniPortExt, 578 Endpoint + 1, 579 IsDoDisablePeriodic); 580 581 Endpoint->Flags &= ~ENDPOINT_FLAG_OPENED; 582 Endpoint->Flags |= ENDPOINT_FLAG_CLOSED; 583 } 584 585 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 586 } 587 588 VOID 589 NTAPI 590 USBPORT_ClosePipe(IN PUSBPORT_DEVICE_HANDLE DeviceHandle, 591 IN PDEVICE_OBJECT FdoDevice, 592 IN PUSBPORT_PIPE_HANDLE PipeHandle) 593 { 594 PUSBPORT_DEVICE_EXTENSION FdoExtension; 595 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 596 PUSBPORT_ENDPOINT Endpoint; 597 PUSBPORT_REGISTRATION_PACKET Packet; 598 PUSB2_TT_EXTENSION TtExtension; 599 ULONG ix; 600 BOOLEAN IsReady; 601 KIRQL OldIrql; 602 603 DPRINT1("USBPORT_ClosePipe \n"); 604 605 FdoExtension = FdoDevice->DeviceExtension; 606 607 if (PipeHandle->Flags & PIPE_HANDLE_FLAG_CLOSED) 608 return; 609 610 USBPORT_RemovePipeHandle(DeviceHandle, PipeHandle); 611 612 PipeHandle->Flags |= PIPE_HANDLE_FLAG_CLOSED; 613 614 if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE) 615 { 616 PipeHandle->Flags &= ~PIPE_HANDLE_FLAG_NULL_PACKET_SIZE; 617 return; 618 } 619 620 Endpoint = PipeHandle->Endpoint; 621 622 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 623 624 if ((Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) && 625 (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)) 626 { 627 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; 628 PdoExtension->Endpoint = NULL; 629 } 630 631 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 632 633 while (TRUE) 634 { 635 IsReady = TRUE; 636 637 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, 638 &Endpoint->EndpointOldIrql); 639 640 if (!IsListEmpty(&Endpoint->PendingTransferList)) 641 IsReady = FALSE; 642 643 if (!IsListEmpty(&Endpoint->TransferList)) 644 IsReady = FALSE; 645 646 if (!IsListEmpty(&Endpoint->CancelList)) 647 IsReady = FALSE; 648 649 if (!IsListEmpty(&Endpoint->AbortList)) 650 IsReady = FALSE; 651 652 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 653 if (Endpoint->StateLast != Endpoint->StateNext) 654 IsReady = FALSE; 655 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 656 657 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, 658 Endpoint->EndpointOldIrql); 659 660 if (InterlockedIncrement(&Endpoint->LockCounter)) 661 IsReady = FALSE; 662 InterlockedDecrement(&Endpoint->LockCounter); 663 664 if (IsReady == TRUE) 665 break; 666 667 USBPORT_Wait(FdoDevice, 1); 668 } 669 670 Endpoint->DeviceHandle = NULL; 671 Packet = &FdoExtension->MiniPortInterface->Packet; 672 673 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 674 { 675 USBPORT_FreeBandwidthUSB2(FdoDevice, Endpoint); 676 677 KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql); 678 679 TtExtension = Endpoint->TtExtension; 680 DPRINT1("USBPORT_ClosePipe: TtExtension - %p\n", TtExtension); 681 682 if (TtExtension) 683 { 684 RemoveEntryList(&Endpoint->TtLink); 685 686 Endpoint->TtLink.Flink = NULL; 687 Endpoint->TtLink.Blink = NULL; 688 689 if (TtExtension->Flags & USB2_TT_EXTENSION_FLAG_DELETED) 690 { 691 if (IsListEmpty(&TtExtension->EndpointList)) 692 { 693 USBPORT_UpdateAllocatedBwTt(TtExtension); 694 695 for (ix = 0; ix < USB2_FRAMES; ix++) 696 { 697 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth; 698 } 699 700 DPRINT1("USBPORT_ClosePipe: ExFreePoolWithTag TtExtension - %p\n", TtExtension); 701 ExFreePoolWithTag(TtExtension, USB_PORT_TAG); 702 } 703 } 704 } 705 706 KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql); 707 } 708 else 709 { 710 USBPORT_FreeBandwidth(FdoDevice, Endpoint); 711 } 712 713 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 714 USBPORT_SetEndpointState(Endpoint, USBPORT_ENDPOINT_REMOVE); 715 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 716 717 USBPORT_SignalWorkerThread(FdoDevice); 718 } 719 720 MPSTATUS 721 NTAPI 722 MiniportOpenEndpoint(IN PDEVICE_OBJECT FdoDevice, 723 IN PUSBPORT_ENDPOINT Endpoint) 724 { 725 PUSBPORT_DEVICE_EXTENSION FdoExtension; 726 PUSBPORT_REGISTRATION_PACKET Packet; 727 KIRQL OldIrql; 728 ULONG TransferType; 729 MPSTATUS MpStatus; 730 731 DPRINT("MiniportOpenEndpoint: Endpoint - %p\n", Endpoint); 732 733 FdoExtension = FdoDevice->DeviceExtension; 734 Packet = &FdoExtension->MiniPortInterface->Packet; 735 736 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 737 738 Endpoint->Flags &= ~ENDPOINT_FLAG_CLOSED; 739 740 MpStatus = Packet->OpenEndpoint(FdoExtension->MiniPortExt, 741 &Endpoint->EndpointProperties, 742 Endpoint + 1); 743 744 if (!MpStatus) 745 { 746 TransferType = Endpoint->EndpointProperties.TransferType; 747 748 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT || 749 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 750 { 751 ++FdoExtension->PeriodicEndpoints; 752 } 753 754 Endpoint->Flags |= ENDPOINT_FLAG_OPENED; 755 } 756 757 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 758 return MpStatus; 759 } 760 761 NTSTATUS 762 NTAPI 763 USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice, 764 IN PUSBPORT_DEVICE_HANDLE DeviceHandle, 765 IN PUSBPORT_PIPE_HANDLE PipeHandle, 766 IN OUT PUSBD_STATUS UsbdStatus) 767 { 768 PUSBPORT_DEVICE_EXTENSION FdoExtension; 769 PUSBPORT_RHDEVICE_EXTENSION PdoExtension; 770 PUSBPORT_REGISTRATION_PACKET Packet; 771 SIZE_T EndpointSize; 772 PUSBPORT_ENDPOINT Endpoint; 773 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 774 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; 775 UCHAR Direction; 776 UCHAR Interval; 777 UCHAR Period; 778 USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0}; 779 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer; 780 MPSTATUS MpStatus; 781 USBD_STATUS USBDStatus; 782 NTSTATUS Status; 783 KIRQL OldIrql; 784 USHORT MaxPacketSize; 785 USHORT AdditionalTransaction; 786 BOOLEAN IsAllocatedBandwidth; 787 788 DPRINT1("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n", 789 DeviceHandle, 790 FdoDevice, 791 PipeHandle); 792 793 FdoExtension = FdoDevice->DeviceExtension; 794 Packet = &FdoExtension->MiniPortInterface->Packet; 795 796 EndpointSize = sizeof(USBPORT_ENDPOINT) + Packet->MiniPortEndpointSize; 797 798 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 799 { 800 EndpointSize += sizeof(USB2_TT_ENDPOINT); 801 } 802 803 if (PipeHandle->EndpointDescriptor.wMaxPacketSize == 0) 804 { 805 USBPORT_AddPipeHandle(DeviceHandle, PipeHandle); 806 807 PipeHandle->Flags = (PipeHandle->Flags & ~PIPE_HANDLE_FLAG_CLOSED) | 808 PIPE_HANDLE_FLAG_NULL_PACKET_SIZE; 809 810 PipeHandle->Endpoint = (PUSBPORT_ENDPOINT)-1; 811 812 return STATUS_SUCCESS; 813 } 814 815 Endpoint = ExAllocatePoolWithTag(NonPagedPool, EndpointSize, USB_PORT_TAG); 816 817 if (!Endpoint) 818 { 819 DPRINT1("USBPORT_OpenPipe: Not allocated Endpoint!\n"); 820 Status = STATUS_INSUFFICIENT_RESOURCES; 821 return Status; 822 } 823 824 RtlZeroMemory(Endpoint, EndpointSize); 825 826 Endpoint->FdoDevice = FdoDevice; 827 Endpoint->DeviceHandle = DeviceHandle; 828 Endpoint->LockCounter = -1; 829 830 Endpoint->TtExtension = DeviceHandle->TtExtension; 831 832 if (DeviceHandle->TtExtension) 833 { 834 ExInterlockedInsertTailList(&DeviceHandle->TtExtension->EndpointList, 835 &Endpoint->TtLink, 836 &FdoExtension->TtSpinLock); 837 } 838 839 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 840 { 841 Endpoint->TtEndpoint = (PUSB2_TT_ENDPOINT)((ULONG_PTR)Endpoint + 842 sizeof(USBPORT_ENDPOINT) + 843 Packet->MiniPortEndpointSize); 844 } 845 else 846 { 847 Endpoint->TtEndpoint = NULL; 848 } 849 850 KeInitializeSpinLock(&Endpoint->EndpointSpinLock); 851 KeInitializeSpinLock(&Endpoint->StateChangeSpinLock); 852 853 InitializeListHead(&Endpoint->PendingTransferList); 854 InitializeListHead(&Endpoint->TransferList); 855 InitializeListHead(&Endpoint->CancelList); 856 InitializeListHead(&Endpoint->AbortList); 857 858 EndpointProperties = &Endpoint->EndpointProperties; 859 EndpointDescriptor = &PipeHandle->EndpointDescriptor; 860 861 MaxPacketSize = EndpointDescriptor->wMaxPacketSize & 0x7FF; 862 AdditionalTransaction = (EndpointDescriptor->wMaxPacketSize >> 11) & 3; 863 864 EndpointProperties->DeviceAddress = DeviceHandle->DeviceAddress; 865 EndpointProperties->DeviceSpeed = DeviceHandle->DeviceSpeed; 866 EndpointProperties->Period = 0; 867 EndpointProperties->EndpointAddress = EndpointDescriptor->bEndpointAddress; 868 EndpointProperties->TransactionPerMicroframe = AdditionalTransaction + 1; 869 EndpointProperties->MaxPacketSize = MaxPacketSize; 870 EndpointProperties->TotalMaxPacketSize = MaxPacketSize * 871 (AdditionalTransaction + 1); 872 873 if (Endpoint->TtExtension) 874 { 875 EndpointProperties->HubAddr = Endpoint->TtExtension->DeviceAddress; 876 } 877 else 878 { 879 EndpointProperties->HubAddr = -1; 880 } 881 882 EndpointProperties->PortNumber = DeviceHandle->PortNumber; 883 884 switch (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) 885 { 886 case USB_ENDPOINT_TYPE_CONTROL: 887 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_CONTROL; 888 889 if (EndpointProperties->EndpointAddress == 0) 890 { 891 EndpointProperties->MaxTransferSize = 0x1000; // OUT Ep0 892 } 893 else 894 { 895 EndpointProperties->MaxTransferSize = 0x10000; 896 } 897 898 break; 899 900 case USB_ENDPOINT_TYPE_ISOCHRONOUS: 901 DPRINT1("USBPORT_OpenPipe: USB_ENDPOINT_TYPE_ISOCHRONOUS UNIMPLEMENTED. FIXME. \n"); 902 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_ISOCHRONOUS; 903 EndpointProperties->MaxTransferSize = 0x1000000; 904 break; 905 906 case USB_ENDPOINT_TYPE_BULK: 907 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_BULK; 908 EndpointProperties->MaxTransferSize = 0x10000; 909 break; 910 911 case USB_ENDPOINT_TYPE_INTERRUPT: 912 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_INTERRUPT; 913 EndpointProperties->MaxTransferSize = 0x400; 914 break; 915 } 916 917 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 918 { 919 if (EndpointProperties->DeviceSpeed == UsbHighSpeed) 920 { 921 Interval = USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval); 922 } 923 else 924 { 925 Interval = EndpointDescriptor->bInterval; 926 } 927 928 EndpointProperties->Period = ENDPOINT_INTERRUPT_32ms; 929 930 if (Interval && (Interval < USB2_FRAMES)) 931 { 932 if ((EndpointProperties->DeviceSpeed != UsbLowSpeed) || 933 (Interval >= ENDPOINT_INTERRUPT_8ms)) 934 { 935 if (!(Interval & ENDPOINT_INTERRUPT_32ms)) 936 { 937 Period = EndpointProperties->Period; 938 939 do 940 { 941 Period >>= 1; 942 } 943 while (!(Period & Interval)); 944 945 EndpointProperties->Period = Period; 946 } 947 } 948 else 949 { 950 EndpointProperties->Period = ENDPOINT_INTERRUPT_8ms; 951 } 952 } 953 } 954 955 if (EndpointProperties->TransferType == USB_ENDPOINT_TYPE_ISOCHRONOUS) 956 { 957 if (EndpointProperties->DeviceSpeed == UsbHighSpeed) 958 { 959 EndpointProperties->Period = 960 USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval); 961 } 962 else 963 { 964 EndpointProperties->Period = ENDPOINT_INTERRUPT_1ms; 965 } 966 } 967 968 if ((DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB) != 0) 969 { 970 Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0; 971 } 972 973 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 974 { 975 IsAllocatedBandwidth = USBPORT_AllocateBandwidthUSB2(FdoDevice, Endpoint); 976 } 977 else 978 { 979 EndpointProperties->UsbBandwidth = USBPORT_CalculateUsbBandwidth(FdoDevice, 980 Endpoint); 981 982 IsAllocatedBandwidth = USBPORT_AllocateBandwidth(FdoDevice, Endpoint); 983 } 984 985 if (!IsAllocatedBandwidth) 986 { 987 Status = USBPORT_USBDStatusToNtStatus(NULL, USBD_STATUS_NO_BANDWIDTH); 988 989 if (UsbdStatus) 990 { 991 *UsbdStatus = USBD_STATUS_NO_BANDWIDTH; 992 } 993 994 goto ExitWithError; 995 } 996 997 Direction = USB_ENDPOINT_DIRECTION_OUT(EndpointDescriptor->bEndpointAddress); 998 EndpointProperties->Direction = Direction; 999 1000 if (DeviceHandle->IsRootHub) 1001 { 1002 Endpoint->EndpointWorker = 0; // USBPORT_RootHubEndpointWorker; 1003 1004 Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0; 1005 1006 Endpoint->StateLast = USBPORT_ENDPOINT_ACTIVE; 1007 Endpoint->StateNext = USBPORT_ENDPOINT_ACTIVE; 1008 1009 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; 1010 1011 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1012 { 1013 PdoExtension->Endpoint = Endpoint; 1014 } 1015 1016 USBDStatus = USBD_STATUS_SUCCESS; 1017 } 1018 else 1019 { 1020 Endpoint->EndpointWorker = 1; // USBPORT_DmaEndpointWorker; 1021 1022 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1023 1024 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt, 1025 &Endpoint->EndpointProperties, 1026 &EndpointRequirements); 1027 1028 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1029 1030 if ((EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_BULK) || 1031 (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)) 1032 { 1033 EndpointProperties->MaxTransferSize = EndpointRequirements.MaxTransferSize; 1034 } 1035 1036 if (EndpointRequirements.HeaderBufferSize) 1037 { 1038 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice, 1039 EndpointRequirements.HeaderBufferSize); 1040 } 1041 else 1042 { 1043 HeaderBuffer = NULL; 1044 } 1045 1046 if (HeaderBuffer || (EndpointRequirements.HeaderBufferSize == 0)) 1047 { 1048 Endpoint->HeaderBuffer = HeaderBuffer; 1049 1050 if (HeaderBuffer) 1051 { 1052 EndpointProperties->BufferVA = HeaderBuffer->VirtualAddress; 1053 EndpointProperties->BufferPA = HeaderBuffer->PhysicalAddress; 1054 EndpointProperties->BufferLength = HeaderBuffer->BufferLength; // BufferLength + LengthPadded; 1055 } 1056 1057 MpStatus = MiniportOpenEndpoint(FdoDevice, Endpoint); 1058 1059 Endpoint->Flags |= ENDPOINT_FLAG_DMA_TYPE; 1060 Endpoint->Flags |= ENDPOINT_FLAG_QUEUENE_EMPTY; 1061 1062 if (MpStatus == 0) 1063 { 1064 ULONG State; 1065 1066 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, 1067 &Endpoint->EndpointOldIrql); 1068 1069 Endpoint->StateLast = USBPORT_ENDPOINT_PAUSED; 1070 Endpoint->StateNext = USBPORT_ENDPOINT_PAUSED; 1071 1072 USBPORT_SetEndpointState(Endpoint, USBPORT_ENDPOINT_ACTIVE); 1073 1074 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, 1075 Endpoint->EndpointOldIrql); 1076 1077 while (TRUE) 1078 { 1079 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, 1080 &Endpoint->EndpointOldIrql); 1081 1082 State = USBPORT_GetEndpointState(Endpoint); 1083 1084 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, 1085 Endpoint->EndpointOldIrql); 1086 1087 if (State == USBPORT_ENDPOINT_ACTIVE) 1088 { 1089 break; 1090 } 1091 1092 USBPORT_Wait(FdoDevice, 1); // 1 msec. 1093 } 1094 } 1095 } 1096 else 1097 { 1098 MpStatus = MP_STATUS_NO_RESOURCES; 1099 Endpoint->HeaderBuffer = NULL; 1100 } 1101 1102 if (MpStatus) 1103 { 1104 USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES; 1105 } 1106 else 1107 { 1108 USBDStatus = USBD_STATUS_SUCCESS; 1109 } 1110 } 1111 1112 if (UsbdStatus) 1113 { 1114 *UsbdStatus = USBDStatus; 1115 } 1116 1117 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus); 1118 1119 if (NT_SUCCESS(Status)) 1120 { 1121 USBPORT_AddPipeHandle(DeviceHandle, PipeHandle); 1122 1123 ExInterlockedInsertTailList(&FdoExtension->EndpointList, 1124 &Endpoint->EndpointLink, 1125 &FdoExtension->EndpointListSpinLock); 1126 1127 PipeHandle->Endpoint = Endpoint; 1128 PipeHandle->Flags &= ~PIPE_HANDLE_FLAG_CLOSED; 1129 1130 return Status; 1131 } 1132 1133 ExitWithError: 1134 1135 if (Endpoint) 1136 { 1137 if (IsAllocatedBandwidth) 1138 { 1139 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) 1140 { 1141 USBPORT_FreeBandwidthUSB2(FdoDevice, Endpoint); 1142 } 1143 else 1144 { 1145 USBPORT_FreeBandwidth(FdoDevice, Endpoint); 1146 } 1147 } 1148 1149 if (Endpoint->TtExtension) 1150 { 1151 KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql); 1152 RemoveEntryList(&Endpoint->TtLink); 1153 KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql); 1154 } 1155 1156 ExFreePoolWithTag(Endpoint, USB_PORT_TAG); 1157 } 1158 1159 DPRINT1("USBPORT_OpenPipe: Status - %lx\n", Status); 1160 return Status; 1161 } 1162 1163 NTSTATUS 1164 NTAPI 1165 USBPORT_ReopenPipe(IN PDEVICE_OBJECT FdoDevice, 1166 IN PUSBPORT_ENDPOINT Endpoint) 1167 { 1168 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1169 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer; 1170 USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0}; 1171 PUSBPORT_REGISTRATION_PACKET Packet; 1172 KIRQL MiniportOldIrql; 1173 NTSTATUS Status; 1174 1175 DPRINT1("USBPORT_ReopenPipe ... \n"); 1176 1177 FdoExtension = FdoDevice->DeviceExtension; 1178 Packet = &FdoExtension->MiniPortInterface->Packet; 1179 1180 while (TRUE) 1181 { 1182 if (!InterlockedIncrement(&Endpoint->LockCounter)) 1183 break; 1184 1185 InterlockedDecrement(&Endpoint->LockCounter); 1186 USBPORT_Wait(FdoDevice, 1); 1187 } 1188 1189 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql); 1190 1191 Packet->SetEndpointState(FdoExtension->MiniPortExt, 1192 Endpoint + 1, 1193 USBPORT_ENDPOINT_REMOVE); 1194 1195 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql); 1196 1197 USBPORT_Wait(FdoDevice, 2); 1198 1199 MiniportCloseEndpoint(FdoDevice, Endpoint); 1200 1201 RtlZeroMemory(Endpoint + 1, 1202 Packet->MiniPortEndpointSize); 1203 1204 if (Endpoint->HeaderBuffer) 1205 { 1206 USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer); 1207 Endpoint->HeaderBuffer = NULL; 1208 } 1209 1210 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql); 1211 1212 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt, 1213 &Endpoint->EndpointProperties, 1214 &EndpointRequirements); 1215 1216 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql); 1217 1218 if (EndpointRequirements.HeaderBufferSize) 1219 { 1220 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice, 1221 EndpointRequirements.HeaderBufferSize); 1222 } 1223 else 1224 { 1225 HeaderBuffer = NULL; 1226 } 1227 1228 if (HeaderBuffer || EndpointRequirements.HeaderBufferSize == 0) 1229 { 1230 Endpoint->HeaderBuffer = HeaderBuffer; 1231 Status = STATUS_SUCCESS; 1232 } 1233 else 1234 { 1235 Endpoint->HeaderBuffer = 0; 1236 Status = STATUS_INSUFFICIENT_RESOURCES; 1237 } 1238 1239 if (Endpoint->HeaderBuffer && HeaderBuffer) 1240 { 1241 Endpoint->EndpointProperties.BufferVA = HeaderBuffer->VirtualAddress; 1242 Endpoint->EndpointProperties.BufferPA = HeaderBuffer->PhysicalAddress; 1243 Endpoint->EndpointProperties.BufferLength = HeaderBuffer->BufferLength; 1244 } 1245 1246 if (NT_SUCCESS(Status)) 1247 { 1248 MiniportOpenEndpoint(FdoDevice, Endpoint); 1249 1250 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1251 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1252 1253 if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE) 1254 { 1255 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock); 1256 1257 Packet->SetEndpointState(FdoExtension->MiniPortExt, 1258 Endpoint + 1, 1259 USBPORT_ENDPOINT_ACTIVE); 1260 1261 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock); 1262 } 1263 1264 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1265 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1266 } 1267 1268 InterlockedDecrement(&Endpoint->LockCounter); 1269 1270 return Status; 1271 } 1272 1273 VOID 1274 NTAPI 1275 USBPORT_FlushClosedEndpointList(IN PDEVICE_OBJECT FdoDevice) 1276 { 1277 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1278 KIRQL OldIrql; 1279 PLIST_ENTRY ClosedList; 1280 PUSBPORT_ENDPOINT Endpoint; 1281 1282 DPRINT_CORE("USBPORT_FlushClosedEndpointList: ... \n"); 1283 1284 FdoExtension = FdoDevice->DeviceExtension; 1285 1286 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql); 1287 ClosedList = &FdoExtension->EndpointClosedList; 1288 1289 while (!IsListEmpty(ClosedList)) 1290 { 1291 Endpoint = CONTAINING_RECORD(ClosedList->Flink, 1292 USBPORT_ENDPOINT, 1293 CloseLink); 1294 1295 RemoveHeadList(ClosedList); 1296 Endpoint->CloseLink.Flink = NULL; 1297 Endpoint->CloseLink.Blink = NULL; 1298 1299 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql); 1300 1301 USBPORT_DeleteEndpoint(FdoDevice, Endpoint); 1302 1303 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql); 1304 } 1305 1306 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql); 1307 } 1308 1309 VOID 1310 NTAPI 1311 USBPORT_InvalidateEndpointHandler(IN PDEVICE_OBJECT FdoDevice, 1312 IN PUSBPORT_ENDPOINT Endpoint, 1313 IN ULONG Type) 1314 { 1315 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1316 PUSBPORT_REGISTRATION_PACKET Packet; 1317 PLIST_ENTRY Entry; 1318 PLIST_ENTRY WorkerLink; 1319 PUSBPORT_ENDPOINT endpoint; 1320 KIRQL OldIrql; 1321 BOOLEAN IsAddEntry = FALSE; 1322 1323 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: Endpoint - %p, Type - %x\n", 1324 Endpoint, 1325 Type); 1326 1327 FdoExtension = FdoDevice->DeviceExtension; 1328 Packet = &FdoExtension->MiniPortInterface->Packet; 1329 1330 if (Endpoint) 1331 { 1332 WorkerLink = &Endpoint->WorkerLink; 1333 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 1334 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: KeAcquireSpinLock \n"); 1335 1336 if ((!WorkerLink->Flink || !WorkerLink->Blink) && 1337 !(Endpoint->Flags & ENDPOINT_FLAG_IDLE) && 1338 USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED) 1339 { 1340 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n"); 1341 InsertTailList(&FdoExtension->WorkerList, WorkerLink); 1342 IsAddEntry = TRUE; 1343 } 1344 1345 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 1346 1347 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) 1348 Type = INVALIDATE_ENDPOINT_WORKER_THREAD; 1349 } 1350 else 1351 { 1352 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 1353 1354 Entry = &FdoExtension->EndpointList; 1355 1356 while (Entry && Entry != &FdoExtension->EndpointList) 1357 { 1358 endpoint = CONTAINING_RECORD(Entry, 1359 USBPORT_ENDPOINT, 1360 EndpointLink); 1361 1362 if (!endpoint->WorkerLink.Flink || !endpoint->WorkerLink.Blink) 1363 { 1364 if (!(endpoint->Flags & ENDPOINT_FLAG_IDLE) && 1365 !(endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) && 1366 USBPORT_GetEndpointState(endpoint) != USBPORT_ENDPOINT_CLOSED) 1367 { 1368 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n"); 1369 InsertTailList(&FdoExtension->WorkerList, &endpoint->WorkerLink); 1370 IsAddEntry = TRUE; 1371 } 1372 } 1373 1374 Entry = endpoint->EndpointLink.Flink; 1375 } 1376 1377 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 1378 } 1379 1380 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND) 1381 { 1382 Type = INVALIDATE_ENDPOINT_WORKER_THREAD; 1383 } 1384 else if (IsAddEntry == FALSE && Type == INVALIDATE_ENDPOINT_INT_NEXT_SOF) 1385 { 1386 Type = INVALIDATE_ENDPOINT_ONLY; 1387 } 1388 1389 switch (Type) 1390 { 1391 case INVALIDATE_ENDPOINT_WORKER_THREAD: 1392 USBPORT_SignalWorkerThread(FdoDevice); 1393 break; 1394 1395 case INVALIDATE_ENDPOINT_WORKER_DPC: 1396 KeInsertQueueDpc(&FdoExtension->WorkerRequestDpc, NULL, NULL); 1397 break; 1398 1399 case INVALIDATE_ENDPOINT_INT_NEXT_SOF: 1400 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1401 Packet->InterruptNextSOF(FdoExtension->MiniPortExt); 1402 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1403 break; 1404 } 1405 } 1406 1407 ULONG 1408 NTAPI 1409 USBPORT_DmaEndpointPaused(IN PDEVICE_OBJECT FdoDevice, 1410 IN PUSBPORT_ENDPOINT Endpoint) 1411 { 1412 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1413 PUSBPORT_REGISTRATION_PACKET Packet; 1414 PLIST_ENTRY Entry; 1415 PUSBPORT_TRANSFER Transfer; 1416 PURB Urb; 1417 ULONG Frame; 1418 ULONG CurrentFrame; 1419 ULONG CompletedLen = 0; 1420 KIRQL OldIrql; 1421 1422 DPRINT_CORE("USBPORT_DmaEndpointPaused \n"); 1423 1424 FdoExtension = FdoDevice->DeviceExtension; 1425 Packet = &FdoExtension->MiniPortInterface->Packet; 1426 1427 Entry = Endpoint->TransferList.Flink; 1428 1429 if (Entry == &Endpoint->TransferList) 1430 return USBPORT_ENDPOINT_ACTIVE; 1431 1432 while (Entry && Entry != &Endpoint->TransferList) 1433 { 1434 Transfer = CONTAINING_RECORD(Entry, 1435 USBPORT_TRANSFER, 1436 TransferLink); 1437 1438 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED)) 1439 { 1440 if (Transfer->Flags & TRANSFER_FLAG_ISO && 1441 Transfer->Flags & TRANSFER_FLAG_SUBMITED && 1442 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1443 { 1444 Urb = Transfer->Urb; 1445 1446 Frame = Urb->UrbIsochronousTransfer.StartFrame + 1447 Urb->UrbIsochronousTransfer.NumberOfPackets; 1448 1449 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1450 CurrentFrame = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt); 1451 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1452 1453 if (Frame + 1 > CurrentFrame) 1454 { 1455 return USBPORT_GetEndpointState(Endpoint); 1456 } 1457 } 1458 1459 if ((Transfer->Flags & TRANSFER_FLAG_SUBMITED) && 1460 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1461 { 1462 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1463 1464 Packet->AbortTransfer(FdoExtension->MiniPortExt, 1465 Endpoint + 1, 1466 Transfer->MiniportTransfer, 1467 &CompletedLen); 1468 1469 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1470 1471 if (Transfer->Flags & TRANSFER_FLAG_ISO) 1472 { 1473 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_FlushIsoTransfer\n"); 1474 ASSERT(FALSE); //USBPORT_FlushIsoTransfer(); 1475 } 1476 else 1477 { 1478 Transfer->CompletedTransferLen = CompletedLen; 1479 } 1480 } 1481 1482 RemoveEntryList(&Transfer->TransferLink); 1483 Entry = Transfer->TransferLink.Flink; 1484 1485 if (Transfer->Flags & TRANSFER_FLAG_SPLITED) 1486 { 1487 USBPORT_CancelSplitTransfer(Transfer); 1488 } 1489 else 1490 { 1491 InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink); 1492 } 1493 } 1494 else 1495 { 1496 Entry = Transfer->TransferLink.Flink; 1497 } 1498 } 1499 1500 return USBPORT_ENDPOINT_ACTIVE; 1501 } 1502 1503 ULONG 1504 NTAPI 1505 USBPORT_DmaEndpointActive(IN PDEVICE_OBJECT FdoDevice, 1506 IN PUSBPORT_ENDPOINT Endpoint) 1507 { 1508 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1509 PUSBPORT_REGISTRATION_PACKET Packet; 1510 PLIST_ENTRY Entry; 1511 PUSBPORT_TRANSFER Transfer; 1512 LARGE_INTEGER TimeOut; 1513 MPSTATUS MpStatus; 1514 KIRQL OldIrql; 1515 1516 DPRINT_CORE("USBPORT_DmaEndpointActive \n"); 1517 1518 FdoExtension = FdoDevice->DeviceExtension; 1519 1520 Entry = Endpoint->TransferList.Flink; 1521 1522 while (Entry && Entry != &Endpoint->TransferList) 1523 { 1524 Transfer = CONTAINING_RECORD(Entry, 1525 USBPORT_TRANSFER, 1526 TransferLink); 1527 1528 if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED) && 1529 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1530 { 1531 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1532 1533 Packet = &FdoExtension->MiniPortInterface->Packet; 1534 1535 if (Transfer->Flags & TRANSFER_FLAG_ISO) 1536 { 1537 DPRINT1("USBPORT_DmaEndpointActive: FIXME call SubmitIsoTransfer\n"); 1538 1539 MpStatus = Packet->SubmitIsoTransfer(FdoExtension->MiniPortExt, 1540 Endpoint + 1, 1541 &Transfer->TransferParameters, 1542 Transfer->MiniportTransfer, 1543 NULL);//&Transfer->IsoTransferParameters); 1544 } 1545 else 1546 { 1547 MpStatus = Packet->SubmitTransfer(FdoExtension->MiniPortExt, 1548 Endpoint + 1, 1549 &Transfer->TransferParameters, 1550 Transfer->MiniportTransfer, 1551 &Transfer->SgList); 1552 } 1553 1554 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1555 1556 if (MpStatus) 1557 { 1558 if ((MpStatus != MP_STATUS_FAILURE) && Transfer->Flags & TRANSFER_FLAG_ISO) 1559 { 1560 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_ErrorCompleteIsoTransfer\n"); 1561 ASSERT(FALSE); //USBPORT_ErrorCompleteIsoTransfer(); 1562 } 1563 1564 return USBPORT_ENDPOINT_ACTIVE; 1565 } 1566 1567 Transfer->Flags |= TRANSFER_FLAG_SUBMITED; 1568 KeQuerySystemTime(&Transfer->Time); 1569 1570 TimeOut.QuadPart = 10000 * Transfer->TimeOut; 1571 Transfer->Time.QuadPart += TimeOut.QuadPart; 1572 } 1573 1574 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED)) 1575 { 1576 return USBPORT_ENDPOINT_PAUSED; 1577 } 1578 1579 Entry = Transfer->TransferLink.Flink; 1580 } 1581 1582 return USBPORT_ENDPOINT_ACTIVE; 1583 } 1584 1585 VOID 1586 NTAPI 1587 USBPORT_DmaEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint) 1588 { 1589 PDEVICE_OBJECT FdoDevice; 1590 ULONG PrevState; 1591 ULONG EndpointState; 1592 BOOLEAN IsPaused = FALSE; 1593 1594 DPRINT_CORE("USBPORT_DmaEndpointWorker ... \n"); 1595 1596 FdoDevice = Endpoint->FdoDevice; 1597 1598 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1599 1600 PrevState = USBPORT_GetEndpointState(Endpoint); 1601 1602 if (PrevState == USBPORT_ENDPOINT_PAUSED) 1603 { 1604 EndpointState = USBPORT_DmaEndpointPaused(FdoDevice, Endpoint); 1605 } 1606 else if (PrevState == USBPORT_ENDPOINT_ACTIVE) 1607 { 1608 EndpointState = USBPORT_DmaEndpointActive(FdoDevice, Endpoint); 1609 } 1610 else 1611 { 1612 #ifndef NDEBUG_USBPORT_CORE 1613 DPRINT1("USBPORT_DmaEndpointWorker: DbgBreakPoint. EndpointState - %x\n", 1614 EndpointState); 1615 DbgBreakPoint(); 1616 #endif 1617 EndpointState = USBPORT_ENDPOINT_UNKNOWN; 1618 } 1619 1620 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1621 1622 USBPORT_FlushCancelList(Endpoint); 1623 1624 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1625 1626 if (EndpointState == PrevState) 1627 { 1628 if (EndpointState == USBPORT_ENDPOINT_PAUSED) 1629 { 1630 IsPaused = TRUE; 1631 } 1632 } 1633 else 1634 { 1635 USBPORT_SetEndpointState(Endpoint, EndpointState); 1636 } 1637 1638 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1639 1640 if (IsPaused) 1641 { 1642 USBPORT_InvalidateEndpointHandler(FdoDevice, 1643 Endpoint, 1644 INVALIDATE_ENDPOINT_WORKER_THREAD); 1645 } 1646 1647 DPRINT_CORE("USBPORT_DmaEndpointWorker exit \n"); 1648 } 1649 1650 BOOLEAN 1651 NTAPI 1652 USBPORT_EndpointWorker(IN PUSBPORT_ENDPOINT Endpoint, 1653 IN BOOLEAN LockNotChecked) 1654 { 1655 PDEVICE_OBJECT FdoDevice; 1656 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1657 PUSBPORT_REGISTRATION_PACKET Packet; 1658 ULONG EndpointState; 1659 1660 DPRINT_CORE("USBPORT_EndpointWorker: Endpoint - %p, LockNotChecked - %x\n", 1661 Endpoint, 1662 LockNotChecked); 1663 1664 FdoDevice = Endpoint->FdoDevice; 1665 FdoExtension = FdoDevice->DeviceExtension; 1666 Packet = &FdoExtension->MiniPortInterface->Packet; 1667 1668 if (LockNotChecked == FALSE) 1669 { 1670 if (InterlockedIncrement(&Endpoint->LockCounter)) 1671 { 1672 InterlockedDecrement(&Endpoint->LockCounter); 1673 DPRINT_CORE("USBPORT_EndpointWorker: LockCounter > 0\n"); 1674 return TRUE; 1675 } 1676 } 1677 1678 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 1679 1680 KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock); 1681 1682 if (USBPORT_GetEndpointState(Endpoint) == USBPORT_ENDPOINT_CLOSED) 1683 { 1684 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1685 InterlockedDecrement(&Endpoint->LockCounter); 1686 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_CLOSED. return FALSE\n"); 1687 return FALSE; 1688 } 1689 1690 if ((Endpoint->Flags & (ENDPOINT_FLAG_ROOTHUB_EP0 | ENDPOINT_FLAG_NUKE)) == 0) 1691 { 1692 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock); 1693 Packet->PollEndpoint(FdoExtension->MiniPortExt, Endpoint + 1); 1694 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock); 1695 } 1696 1697 EndpointState = USBPORT_GetEndpointState(Endpoint); 1698 1699 if (EndpointState == USBPORT_ENDPOINT_REMOVE) 1700 { 1701 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1702 Endpoint->StateLast = USBPORT_ENDPOINT_CLOSED; 1703 Endpoint->StateNext = USBPORT_ENDPOINT_CLOSED; 1704 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1705 1706 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1707 1708 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock); 1709 1710 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList, 1711 &Endpoint->CloseLink, 1712 &FdoExtension->EndpointClosedSpinLock); 1713 1714 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock); 1715 1716 InterlockedDecrement(&Endpoint->LockCounter); 1717 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_REMOVE. return FALSE\n"); 1718 return FALSE; 1719 } 1720 1721 if (!IsListEmpty(&Endpoint->PendingTransferList) || 1722 !IsListEmpty(&Endpoint->TransferList) || 1723 !IsListEmpty(&Endpoint->CancelList)) 1724 { 1725 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1726 1727 EndpointState = USBPORT_GetEndpointState(Endpoint); 1728 1729 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1730 if (EndpointState == Endpoint->StateNext) 1731 { 1732 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1733 1734 if (Endpoint->EndpointWorker) 1735 { 1736 USBPORT_DmaEndpointWorker(Endpoint); 1737 } 1738 else 1739 { 1740 USBPORT_RootHubEndpointWorker(Endpoint); 1741 } 1742 1743 USBPORT_FlushAbortList(Endpoint); 1744 1745 InterlockedDecrement(&Endpoint->LockCounter); 1746 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n"); 1747 return FALSE; 1748 } 1749 1750 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1751 InterlockedDecrement(&Endpoint->LockCounter); 1752 1753 DPRINT_CORE("USBPORT_EndpointWorker: return TRUE\n"); 1754 return TRUE; 1755 } 1756 1757 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1758 1759 USBPORT_FlushAbortList(Endpoint); 1760 1761 InterlockedDecrement(&Endpoint->LockCounter); 1762 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n"); 1763 return FALSE; 1764 } 1765