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