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(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1190 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock); 1191 1192 Packet->SetEndpointState(FdoExtension->MiniPortExt, 1193 Endpoint + 1, 1194 USBPORT_ENDPOINT_REMOVE); 1195 1196 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock); 1197 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1198 1199 USBPORT_Wait(FdoDevice, 2); 1200 1201 MiniportCloseEndpoint(FdoDevice, Endpoint); 1202 1203 RtlZeroMemory(Endpoint + 1, 1204 Packet->MiniPortEndpointSize); 1205 1206 if (Endpoint->HeaderBuffer) 1207 { 1208 USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer); 1209 Endpoint->HeaderBuffer = NULL; 1210 } 1211 1212 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql); 1213 1214 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt, 1215 &Endpoint->EndpointProperties, 1216 &EndpointRequirements); 1217 1218 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql); 1219 1220 if (EndpointRequirements.HeaderBufferSize) 1221 { 1222 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice, 1223 EndpointRequirements.HeaderBufferSize); 1224 } 1225 else 1226 { 1227 HeaderBuffer = NULL; 1228 } 1229 1230 if (HeaderBuffer || EndpointRequirements.HeaderBufferSize == 0) 1231 { 1232 Endpoint->HeaderBuffer = HeaderBuffer; 1233 Status = STATUS_SUCCESS; 1234 } 1235 else 1236 { 1237 Endpoint->HeaderBuffer = 0; 1238 Status = STATUS_INSUFFICIENT_RESOURCES; 1239 } 1240 1241 if (Endpoint->HeaderBuffer && HeaderBuffer) 1242 { 1243 Endpoint->EndpointProperties.BufferVA = HeaderBuffer->VirtualAddress; 1244 Endpoint->EndpointProperties.BufferPA = HeaderBuffer->PhysicalAddress; 1245 Endpoint->EndpointProperties.BufferLength = HeaderBuffer->BufferLength; 1246 } 1247 1248 if (NT_SUCCESS(Status)) 1249 { 1250 MiniportOpenEndpoint(FdoDevice, Endpoint); 1251 1252 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1253 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1254 1255 if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE) 1256 { 1257 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1258 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock); 1259 1260 Packet->SetEndpointState(FdoExtension->MiniPortExt, 1261 Endpoint + 1, 1262 USBPORT_ENDPOINT_ACTIVE); 1263 1264 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock); 1265 } 1266 else 1267 { 1268 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1269 } 1270 1271 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1272 } 1273 1274 InterlockedDecrement(&Endpoint->LockCounter); 1275 1276 return Status; 1277 } 1278 1279 VOID 1280 NTAPI 1281 USBPORT_FlushClosedEndpointList(IN PDEVICE_OBJECT FdoDevice) 1282 { 1283 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1284 KIRQL OldIrql; 1285 PLIST_ENTRY ClosedList; 1286 PUSBPORT_ENDPOINT Endpoint; 1287 1288 DPRINT_CORE("USBPORT_FlushClosedEndpointList: ... \n"); 1289 1290 FdoExtension = FdoDevice->DeviceExtension; 1291 1292 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql); 1293 ClosedList = &FdoExtension->EndpointClosedList; 1294 1295 while (!IsListEmpty(ClosedList)) 1296 { 1297 Endpoint = CONTAINING_RECORD(ClosedList->Flink, 1298 USBPORT_ENDPOINT, 1299 CloseLink); 1300 1301 RemoveHeadList(ClosedList); 1302 Endpoint->CloseLink.Flink = NULL; 1303 Endpoint->CloseLink.Blink = NULL; 1304 1305 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql); 1306 1307 USBPORT_DeleteEndpoint(FdoDevice, Endpoint); 1308 1309 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql); 1310 } 1311 1312 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql); 1313 } 1314 1315 VOID 1316 NTAPI 1317 USBPORT_InvalidateEndpointHandler(IN PDEVICE_OBJECT FdoDevice, 1318 IN PUSBPORT_ENDPOINT Endpoint, 1319 IN ULONG Type) 1320 { 1321 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1322 PUSBPORT_REGISTRATION_PACKET Packet; 1323 PLIST_ENTRY Entry; 1324 PLIST_ENTRY WorkerLink; 1325 PUSBPORT_ENDPOINT endpoint; 1326 KIRQL OldIrql; 1327 BOOLEAN IsAddEntry = FALSE; 1328 1329 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: Endpoint - %p, Type - %x\n", 1330 Endpoint, 1331 Type); 1332 1333 FdoExtension = FdoDevice->DeviceExtension; 1334 Packet = &FdoExtension->MiniPortInterface->Packet; 1335 1336 if (Endpoint) 1337 { 1338 WorkerLink = &Endpoint->WorkerLink; 1339 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 1340 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: KeAcquireSpinLock \n"); 1341 1342 if ((!WorkerLink->Flink || !WorkerLink->Blink) && 1343 !(Endpoint->Flags & ENDPOINT_FLAG_IDLE) && 1344 USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED) 1345 { 1346 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n"); 1347 InsertTailList(&FdoExtension->WorkerList, WorkerLink); 1348 IsAddEntry = TRUE; 1349 } 1350 1351 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 1352 1353 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) 1354 Type = INVALIDATE_ENDPOINT_WORKER_THREAD; 1355 } 1356 else 1357 { 1358 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql); 1359 1360 for (Entry = FdoExtension->EndpointList.Flink; 1361 Entry && Entry != &FdoExtension->EndpointList; 1362 Entry = Entry->Flink) 1363 { 1364 endpoint = CONTAINING_RECORD(Entry, 1365 USBPORT_ENDPOINT, 1366 EndpointLink); 1367 1368 if (!endpoint->WorkerLink.Flink || !endpoint->WorkerLink.Blink) 1369 { 1370 if (!(endpoint->Flags & ENDPOINT_FLAG_IDLE) && 1371 !(endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) && 1372 USBPORT_GetEndpointState(endpoint) != USBPORT_ENDPOINT_CLOSED) 1373 { 1374 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n"); 1375 InsertTailList(&FdoExtension->WorkerList, &endpoint->WorkerLink); 1376 IsAddEntry = TRUE; 1377 } 1378 } 1379 } 1380 1381 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql); 1382 } 1383 1384 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND) 1385 { 1386 Type = INVALIDATE_ENDPOINT_WORKER_THREAD; 1387 } 1388 else if (IsAddEntry == FALSE && Type == INVALIDATE_ENDPOINT_INT_NEXT_SOF) 1389 { 1390 Type = INVALIDATE_ENDPOINT_ONLY; 1391 } 1392 1393 switch (Type) 1394 { 1395 case INVALIDATE_ENDPOINT_WORKER_THREAD: 1396 USBPORT_SignalWorkerThread(FdoDevice); 1397 break; 1398 1399 case INVALIDATE_ENDPOINT_WORKER_DPC: 1400 KeInsertQueueDpc(&FdoExtension->WorkerRequestDpc, NULL, NULL); 1401 break; 1402 1403 case INVALIDATE_ENDPOINT_INT_NEXT_SOF: 1404 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1405 Packet->InterruptNextSOF(FdoExtension->MiniPortExt); 1406 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1407 break; 1408 } 1409 } 1410 1411 ULONG 1412 NTAPI 1413 USBPORT_DmaEndpointPaused(IN PDEVICE_OBJECT FdoDevice, 1414 IN PUSBPORT_ENDPOINT Endpoint) 1415 { 1416 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1417 PUSBPORT_REGISTRATION_PACKET Packet; 1418 PLIST_ENTRY Entry; 1419 PUSBPORT_TRANSFER Transfer; 1420 PURB Urb; 1421 ULONG Frame; 1422 ULONG CurrentFrame; 1423 ULONG CompletedLen = 0; 1424 KIRQL OldIrql; 1425 1426 DPRINT_CORE("USBPORT_DmaEndpointPaused \n"); 1427 1428 FdoExtension = FdoDevice->DeviceExtension; 1429 Packet = &FdoExtension->MiniPortInterface->Packet; 1430 1431 Entry = Endpoint->TransferList.Flink; 1432 1433 if (Entry == &Endpoint->TransferList) 1434 return USBPORT_ENDPOINT_ACTIVE; 1435 1436 while (Entry && Entry != &Endpoint->TransferList) 1437 { 1438 Transfer = CONTAINING_RECORD(Entry, 1439 USBPORT_TRANSFER, 1440 TransferLink); 1441 1442 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED)) 1443 { 1444 if (Transfer->Flags & TRANSFER_FLAG_ISO && 1445 Transfer->Flags & TRANSFER_FLAG_SUBMITED && 1446 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1447 { 1448 Urb = Transfer->Urb; 1449 1450 Frame = Urb->UrbIsochronousTransfer.StartFrame + 1451 Urb->UrbIsochronousTransfer.NumberOfPackets; 1452 1453 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1454 CurrentFrame = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt); 1455 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1456 1457 if (Frame + 1 > CurrentFrame) 1458 { 1459 return USBPORT_GetEndpointState(Endpoint); 1460 } 1461 } 1462 1463 if ((Transfer->Flags & TRANSFER_FLAG_SUBMITED) && 1464 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1465 { 1466 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1467 1468 Packet->AbortTransfer(FdoExtension->MiniPortExt, 1469 Endpoint + 1, 1470 Transfer->MiniportTransfer, 1471 &CompletedLen); 1472 1473 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1474 1475 if (Transfer->Flags & TRANSFER_FLAG_ISO) 1476 { 1477 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_FlushIsoTransfer\n"); 1478 ASSERT(FALSE); //USBPORT_FlushIsoTransfer(); 1479 } 1480 else 1481 { 1482 Transfer->CompletedTransferLen = CompletedLen; 1483 } 1484 } 1485 1486 RemoveEntryList(&Transfer->TransferLink); 1487 Entry = Transfer->TransferLink.Flink; 1488 1489 if (Transfer->Flags & TRANSFER_FLAG_SPLITED) 1490 { 1491 USBPORT_CancelSplitTransfer(Transfer); 1492 } 1493 else 1494 { 1495 InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink); 1496 } 1497 } 1498 else 1499 { 1500 Entry = Transfer->TransferLink.Flink; 1501 } 1502 } 1503 1504 return USBPORT_ENDPOINT_ACTIVE; 1505 } 1506 1507 ULONG 1508 NTAPI 1509 USBPORT_DmaEndpointActive(IN PDEVICE_OBJECT FdoDevice, 1510 IN PUSBPORT_ENDPOINT Endpoint) 1511 { 1512 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1513 PUSBPORT_REGISTRATION_PACKET Packet; 1514 PLIST_ENTRY Entry; 1515 PUSBPORT_TRANSFER Transfer; 1516 LARGE_INTEGER TimeOut; 1517 MPSTATUS MpStatus; 1518 KIRQL OldIrql; 1519 1520 DPRINT_CORE("USBPORT_DmaEndpointActive \n"); 1521 1522 FdoExtension = FdoDevice->DeviceExtension; 1523 1524 Entry = Endpoint->TransferList.Flink; 1525 1526 while (Entry && Entry != &Endpoint->TransferList) 1527 { 1528 Transfer = CONTAINING_RECORD(Entry, 1529 USBPORT_TRANSFER, 1530 TransferLink); 1531 1532 if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED) && 1533 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE)) 1534 { 1535 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 1536 1537 Packet = &FdoExtension->MiniPortInterface->Packet; 1538 1539 if (Transfer->Flags & TRANSFER_FLAG_ISO) 1540 { 1541 DPRINT1("USBPORT_DmaEndpointActive: FIXME call SubmitIsoTransfer\n"); 1542 1543 MpStatus = Packet->SubmitIsoTransfer(FdoExtension->MiniPortExt, 1544 Endpoint + 1, 1545 &Transfer->TransferParameters, 1546 Transfer->MiniportTransfer, 1547 NULL);//&Transfer->IsoTransferParameters); 1548 } 1549 else 1550 { 1551 MpStatus = Packet->SubmitTransfer(FdoExtension->MiniPortExt, 1552 Endpoint + 1, 1553 &Transfer->TransferParameters, 1554 Transfer->MiniportTransfer, 1555 &Transfer->SgList); 1556 } 1557 1558 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 1559 1560 if (MpStatus) 1561 { 1562 if ((MpStatus != MP_STATUS_FAILURE) && Transfer->Flags & TRANSFER_FLAG_ISO) 1563 { 1564 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_ErrorCompleteIsoTransfer\n"); 1565 ASSERT(FALSE); //USBPORT_ErrorCompleteIsoTransfer(); 1566 } 1567 1568 return USBPORT_ENDPOINT_ACTIVE; 1569 } 1570 1571 Transfer->Flags |= TRANSFER_FLAG_SUBMITED; 1572 KeQuerySystemTime(&Transfer->Time); 1573 1574 TimeOut.QuadPart = 10000 * Transfer->TimeOut; 1575 Transfer->Time.QuadPart += TimeOut.QuadPart; 1576 } 1577 1578 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED)) 1579 { 1580 return USBPORT_ENDPOINT_PAUSED; 1581 } 1582 1583 Entry = Transfer->TransferLink.Flink; 1584 } 1585 1586 return USBPORT_ENDPOINT_ACTIVE; 1587 } 1588 1589 VOID 1590 NTAPI 1591 USBPORT_DmaEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint) 1592 { 1593 PDEVICE_OBJECT FdoDevice; 1594 ULONG PrevState; 1595 ULONG EndpointState; 1596 BOOLEAN IsPaused = FALSE; 1597 1598 DPRINT_CORE("USBPORT_DmaEndpointWorker ... \n"); 1599 1600 FdoDevice = Endpoint->FdoDevice; 1601 1602 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1603 1604 PrevState = USBPORT_GetEndpointState(Endpoint); 1605 1606 if (PrevState == USBPORT_ENDPOINT_PAUSED) 1607 { 1608 EndpointState = USBPORT_DmaEndpointPaused(FdoDevice, Endpoint); 1609 } 1610 else if (PrevState == USBPORT_ENDPOINT_ACTIVE) 1611 { 1612 EndpointState = USBPORT_DmaEndpointActive(FdoDevice, Endpoint); 1613 } 1614 else 1615 { 1616 #ifndef NDEBUG_USBPORT_CORE 1617 DPRINT1("USBPORT_DmaEndpointWorker: DbgBreakPoint. EndpointState - %x\n", 1618 EndpointState); 1619 DbgBreakPoint(); 1620 #endif 1621 EndpointState = USBPORT_ENDPOINT_UNKNOWN; 1622 } 1623 1624 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1625 1626 USBPORT_FlushCancelList(Endpoint); 1627 1628 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); 1629 1630 if (EndpointState == PrevState) 1631 { 1632 if (EndpointState == USBPORT_ENDPOINT_PAUSED) 1633 { 1634 IsPaused = TRUE; 1635 } 1636 } 1637 else 1638 { 1639 USBPORT_SetEndpointState(Endpoint, EndpointState); 1640 } 1641 1642 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); 1643 1644 if (IsPaused) 1645 { 1646 USBPORT_InvalidateEndpointHandler(FdoDevice, 1647 Endpoint, 1648 INVALIDATE_ENDPOINT_WORKER_THREAD); 1649 } 1650 1651 DPRINT_CORE("USBPORT_DmaEndpointWorker exit \n"); 1652 } 1653 1654 BOOLEAN 1655 NTAPI 1656 USBPORT_EndpointWorker(IN PUSBPORT_ENDPOINT Endpoint, 1657 IN BOOLEAN LockNotChecked) 1658 { 1659 PDEVICE_OBJECT FdoDevice; 1660 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1661 PUSBPORT_REGISTRATION_PACKET Packet; 1662 ULONG EndpointState; 1663 1664 DPRINT_CORE("USBPORT_EndpointWorker: Endpoint - %p, LockNotChecked - %x\n", 1665 Endpoint, 1666 LockNotChecked); 1667 1668 FdoDevice = Endpoint->FdoDevice; 1669 FdoExtension = FdoDevice->DeviceExtension; 1670 Packet = &FdoExtension->MiniPortInterface->Packet; 1671 1672 if (LockNotChecked == FALSE) 1673 { 1674 if (InterlockedIncrement(&Endpoint->LockCounter)) 1675 { 1676 InterlockedDecrement(&Endpoint->LockCounter); 1677 DPRINT_CORE("USBPORT_EndpointWorker: LockCounter > 0\n"); 1678 return TRUE; 1679 } 1680 } 1681 1682 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 1683 1684 KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock); 1685 1686 if (USBPORT_GetEndpointState(Endpoint) == USBPORT_ENDPOINT_CLOSED) 1687 { 1688 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1689 InterlockedDecrement(&Endpoint->LockCounter); 1690 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_CLOSED. return FALSE\n"); 1691 return FALSE; 1692 } 1693 1694 if ((Endpoint->Flags & (ENDPOINT_FLAG_ROOTHUB_EP0 | ENDPOINT_FLAG_NUKE)) == 0) 1695 { 1696 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock); 1697 Packet->PollEndpoint(FdoExtension->MiniPortExt, Endpoint + 1); 1698 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock); 1699 } 1700 1701 EndpointState = USBPORT_GetEndpointState(Endpoint); 1702 1703 if (EndpointState == USBPORT_ENDPOINT_REMOVE) 1704 { 1705 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1706 Endpoint->StateLast = USBPORT_ENDPOINT_CLOSED; 1707 Endpoint->StateNext = USBPORT_ENDPOINT_CLOSED; 1708 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1709 1710 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1711 1712 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock); 1713 1714 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList, 1715 &Endpoint->CloseLink, 1716 &FdoExtension->EndpointClosedSpinLock); 1717 1718 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock); 1719 1720 InterlockedDecrement(&Endpoint->LockCounter); 1721 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_REMOVE. return FALSE\n"); 1722 return FALSE; 1723 } 1724 1725 if (!IsListEmpty(&Endpoint->PendingTransferList) || 1726 !IsListEmpty(&Endpoint->TransferList) || 1727 !IsListEmpty(&Endpoint->CancelList)) 1728 { 1729 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1730 1731 EndpointState = USBPORT_GetEndpointState(Endpoint); 1732 1733 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock); 1734 if (EndpointState == Endpoint->StateNext) 1735 { 1736 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1737 1738 if (Endpoint->EndpointWorker) 1739 { 1740 USBPORT_DmaEndpointWorker(Endpoint); 1741 } 1742 else 1743 { 1744 USBPORT_RootHubEndpointWorker(Endpoint); 1745 } 1746 1747 USBPORT_FlushAbortList(Endpoint); 1748 1749 InterlockedDecrement(&Endpoint->LockCounter); 1750 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n"); 1751 return FALSE; 1752 } 1753 1754 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock); 1755 InterlockedDecrement(&Endpoint->LockCounter); 1756 1757 DPRINT_CORE("USBPORT_EndpointWorker: return TRUE\n"); 1758 return TRUE; 1759 } 1760 1761 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock); 1762 1763 USBPORT_FlushAbortList(Endpoint); 1764 1765 InterlockedDecrement(&Endpoint->LockCounter); 1766 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n"); 1767 return FALSE; 1768 } 1769