[USBPORT] Add support for transaction translators in USBPORT_OpenPipe().
[reactos.git] / drivers / usb / usbport / endpoint.c
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) * 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 EndpointSize += sizeof(USB2_TT_ENDPOINT);
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 Endpoint->TtExtension = DeviceHandle->TtExtension;
676
677 if (DeviceHandle->TtExtension)
678 {
679 ExInterlockedInsertTailList(&DeviceHandle->TtExtension->TtList,
680 &Endpoint->TtLink,
681 &FdoExtension->TtSpinLock);
682 }
683
684 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
685 {
686 Endpoint->TtEndpoint = (PUSB2_TT_ENDPOINT)((ULONG_PTR)Endpoint +
687 sizeof(USBPORT_ENDPOINT) +
688 Packet->MiniPortEndpointSize);
689 }
690 else
691 {
692 Endpoint->TtEndpoint = NULL;
693 }
694
695 KeInitializeSpinLock(&Endpoint->EndpointSpinLock);
696 KeInitializeSpinLock(&Endpoint->StateChangeSpinLock);
697
698 InitializeListHead(&Endpoint->PendingTransferList);
699 InitializeListHead(&Endpoint->TransferList);
700 InitializeListHead(&Endpoint->CancelList);
701 InitializeListHead(&Endpoint->AbortList);
702
703 EndpointProperties = &Endpoint->EndpointProperties;
704 EndpointDescriptor = &PipeHandle->EndpointDescriptor;
705
706 MaxPacketSize = EndpointDescriptor->wMaxPacketSize & 0x7FF;
707 AdditionalTransaction = (EndpointDescriptor->wMaxPacketSize >> 11) & 3;
708
709 EndpointProperties->DeviceAddress = DeviceHandle->DeviceAddress;
710 EndpointProperties->DeviceSpeed = DeviceHandle->DeviceSpeed;
711 EndpointProperties->Period = 0;
712 EndpointProperties->EndpointAddress = EndpointDescriptor->bEndpointAddress;
713 EndpointProperties->TransactionPerMicroframe = AdditionalTransaction + 1;
714 EndpointProperties->MaxPacketSize = MaxPacketSize;
715 EndpointProperties->TotalMaxPacketSize = MaxPacketSize *
716 (AdditionalTransaction + 1);
717
718 if (Endpoint->TtExtension)
719 {
720 EndpointProperties->HubAddr = Endpoint->TtExtension->DeviceAddress;
721 }
722 else
723 {
724 EndpointProperties->HubAddr = -1;
725 }
726
727 EndpointProperties->PortNumber = DeviceHandle->PortNumber;
728
729 switch (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
730 {
731 case USB_ENDPOINT_TYPE_CONTROL:
732 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_CONTROL;
733
734 if (EndpointProperties->EndpointAddress == 0)
735 {
736 EndpointProperties->MaxTransferSize = 0x1000; // OUT Ep0
737 }
738 else
739 {
740 EndpointProperties->MaxTransferSize = 0x10000;
741 }
742
743 break;
744
745 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
746 DPRINT1("USBPORT_OpenPipe: USB_ENDPOINT_TYPE_ISOCHRONOUS UNIMPLEMENTED. FIXME. \n");
747 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_ISOCHRONOUS;
748 EndpointProperties->MaxTransferSize = 0x1000000;
749 break;
750
751 case USB_ENDPOINT_TYPE_BULK:
752 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_BULK;
753 EndpointProperties->MaxTransferSize = 0x10000;
754 break;
755
756 case USB_ENDPOINT_TYPE_INTERRUPT:
757 EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_INTERRUPT;
758 EndpointProperties->MaxTransferSize = 0x400;
759 break;
760 }
761
762 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
763 {
764 if (EndpointProperties->DeviceSpeed == UsbHighSpeed)
765 {
766 Interval = USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval);
767 }
768 else
769 {
770 Interval = EndpointDescriptor->bInterval;
771 }
772
773 EndpointProperties->Period = ENDPOINT_INTERRUPT_32ms;
774
775 if (Interval && (Interval < USB2_FRAMES))
776 {
777 if ((EndpointProperties->DeviceSpeed != UsbLowSpeed) ||
778 (Interval >= ENDPOINT_INTERRUPT_8ms))
779 {
780 if (!(Interval & ENDPOINT_INTERRUPT_32ms))
781 {
782 Period = EndpointProperties->Period;
783
784 do
785 {
786 Period >>= 1;
787 }
788 while (!(Period & Interval));
789
790 EndpointProperties->Period = Period;
791 }
792 }
793 else
794 {
795 EndpointProperties->Period = ENDPOINT_INTERRUPT_8ms;
796 }
797 }
798 }
799
800 if (EndpointProperties->TransferType == USB_ENDPOINT_TYPE_ISOCHRONOUS)
801 {
802 if (EndpointProperties->DeviceSpeed == UsbHighSpeed)
803 {
804 EndpointProperties->Period =
805 USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval);
806 }
807 else
808 {
809 EndpointProperties->Period = ENDPOINT_INTERRUPT_1ms;
810 }
811 }
812
813 if ((DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB) != 0)
814 {
815 Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0;
816 }
817
818 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
819 {
820 IsAllocatedBandwidth = USBPORT_AllocateBandwidthUSB2(FdoDevice, Endpoint);
821 }
822 else
823 {
824 EndpointProperties->UsbBandwidth = USBPORT_CalculateUsbBandwidth(FdoDevice,
825 Endpoint);
826
827 IsAllocatedBandwidth = USBPORT_AllocateBandwidth(FdoDevice, Endpoint);
828 }
829
830 if (!IsAllocatedBandwidth)
831 {
832 Status = USBPORT_USBDStatusToNtStatus(NULL, USBD_STATUS_NO_BANDWIDTH);
833
834 if (UsbdStatus)
835 {
836 *UsbdStatus = USBD_STATUS_NO_BANDWIDTH;
837 }
838
839 goto ExitWithError;
840 }
841
842 Direction = USB_ENDPOINT_DIRECTION_OUT(EndpointDescriptor->bEndpointAddress);
843 EndpointProperties->Direction = Direction;
844
845 if (DeviceHandle->IsRootHub)
846 {
847 Endpoint->EndpointWorker = 0; // USBPORT_RootHubEndpointWorker;
848
849 Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0;
850
851 Endpoint->StateLast = USBPORT_ENDPOINT_ACTIVE;
852 Endpoint->StateNext = USBPORT_ENDPOINT_ACTIVE;
853
854 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
855
856 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
857 {
858 PdoExtension->Endpoint = Endpoint;
859 }
860
861 USBDStatus = USBD_STATUS_SUCCESS;
862 }
863 else
864 {
865 Endpoint->EndpointWorker = 1; // USBPORT_DmaEndpointWorker;
866
867 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
868
869 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
870 &Endpoint->EndpointProperties,
871 &EndpointRequirements);
872
873 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
874
875 if ((EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_BULK) ||
876 (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT))
877 {
878 EndpointProperties->MaxTransferSize = EndpointRequirements.MaxTransferSize;
879 }
880
881 if (EndpointRequirements.HeaderBufferSize)
882 {
883 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
884 EndpointRequirements.HeaderBufferSize);
885 }
886 else
887 {
888 HeaderBuffer = NULL;
889 }
890
891 if (HeaderBuffer || (EndpointRequirements.HeaderBufferSize == 0))
892 {
893 Endpoint->HeaderBuffer = HeaderBuffer;
894
895 if (HeaderBuffer)
896 {
897 EndpointProperties->BufferVA = HeaderBuffer->VirtualAddress;
898 EndpointProperties->BufferPA = HeaderBuffer->PhysicalAddress;
899 EndpointProperties->BufferLength = HeaderBuffer->BufferLength; // BufferLength + LengthPadded;
900 }
901
902 MpStatus = MiniportOpenEndpoint(FdoDevice, Endpoint);
903
904 Endpoint->Flags |= ENDPOINT_FLAG_DMA_TYPE;
905 Endpoint->Flags |= ENDPOINT_FLAG_QUEUENE_EMPTY;
906
907 if (MpStatus == 0)
908 {
909 ULONG State;
910
911 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
912 &Endpoint->EndpointOldIrql);
913
914 Endpoint->StateLast = USBPORT_ENDPOINT_PAUSED;
915 Endpoint->StateNext = USBPORT_ENDPOINT_PAUSED;
916
917 USBPORT_SetEndpointState(Endpoint, USBPORT_ENDPOINT_ACTIVE);
918
919 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
920 Endpoint->EndpointOldIrql);
921
922 while (TRUE)
923 {
924 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
925 &Endpoint->EndpointOldIrql);
926
927 State = USBPORT_GetEndpointState(Endpoint);
928
929 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
930 Endpoint->EndpointOldIrql);
931
932 if (State == USBPORT_ENDPOINT_ACTIVE)
933 {
934 break;
935 }
936
937 USBPORT_Wait(FdoDevice, 1); // 1 msec.
938 }
939 }
940 }
941 else
942 {
943 MpStatus = MP_STATUS_NO_RESOURCES;
944 Endpoint->HeaderBuffer = NULL;
945 }
946
947 if (MpStatus)
948 {
949 USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
950 }
951 else
952 {
953 USBDStatus = USBD_STATUS_SUCCESS;
954 }
955 }
956
957 if (UsbdStatus)
958 {
959 *UsbdStatus = USBDStatus;
960 }
961
962 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
963
964 if (NT_SUCCESS(Status))
965 {
966 USBPORT_AddPipeHandle(DeviceHandle, PipeHandle);
967
968 ExInterlockedInsertTailList(&FdoExtension->EndpointList,
969 &Endpoint->EndpointLink,
970 &FdoExtension->EndpointListSpinLock);
971
972 PipeHandle->Endpoint = Endpoint;
973 PipeHandle->Flags &= ~PIPE_HANDLE_FLAG_CLOSED;
974
975 return Status;
976 }
977
978 ExitWithError:
979
980 if (Endpoint)
981 {
982 if (IsAllocatedBandwidth)
983 {
984 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
985 {
986 USBPORT_FreeBandwidthUSB2(FdoDevice, Endpoint);
987 }
988 else
989 {
990 USBPORT_FreeBandwidth(FdoDevice, Endpoint);
991 }
992 }
993
994 if (Endpoint->TtExtension)
995 {
996 KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
997 RemoveEntryList(&Endpoint->TtLink);
998 KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
999 }
1000
1001 ExFreePoolWithTag(Endpoint, USB_PORT_TAG);
1002 }
1003
1004 DPRINT1("USBPORT_OpenPipe: Status - %lx\n", Status);
1005 return Status;
1006 }
1007
1008 NTSTATUS
1009 NTAPI
1010 USBPORT_ReopenPipe(IN PDEVICE_OBJECT FdoDevice,
1011 IN PUSBPORT_ENDPOINT Endpoint)
1012 {
1013 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1014 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
1015 USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0};
1016 PUSBPORT_REGISTRATION_PACKET Packet;
1017 KIRQL MiniportOldIrql;
1018 NTSTATUS Status;
1019
1020 DPRINT("USBPORT_ReopenPipe ... \n");
1021
1022 FdoExtension = FdoDevice->DeviceExtension;
1023 Packet = &FdoExtension->MiniPortInterface->Packet;
1024
1025 while (TRUE)
1026 {
1027 if (!InterlockedIncrement(&Endpoint->LockCounter))
1028 break;
1029
1030 InterlockedDecrement(&Endpoint->LockCounter);
1031 USBPORT_Wait(FdoDevice, 1);
1032 }
1033
1034 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql);
1035
1036 Packet->SetEndpointState(FdoExtension->MiniPortExt,
1037 Endpoint + 1,
1038 USBPORT_ENDPOINT_REMOVE);
1039
1040 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql);
1041
1042 USBPORT_Wait(FdoDevice, 2);
1043
1044 MiniportCloseEndpoint(FdoDevice, Endpoint);
1045
1046 RtlZeroMemory(Endpoint + 1,
1047 Packet->MiniPortEndpointSize);
1048
1049 if (Endpoint->HeaderBuffer)
1050 {
1051 USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer);
1052 Endpoint->HeaderBuffer = NULL;
1053 }
1054
1055 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql);
1056
1057 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
1058 &Endpoint->EndpointProperties,
1059 &EndpointRequirements);
1060
1061 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql);
1062
1063 if (EndpointRequirements.HeaderBufferSize)
1064 {
1065 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
1066 EndpointRequirements.HeaderBufferSize);
1067 }
1068 else
1069 {
1070 HeaderBuffer = NULL;
1071 }
1072
1073 if (HeaderBuffer || EndpointRequirements.HeaderBufferSize == 0)
1074 {
1075 Endpoint->HeaderBuffer = HeaderBuffer;
1076 Status = STATUS_SUCCESS;
1077 }
1078 else
1079 {
1080 Endpoint->HeaderBuffer = 0;
1081 Status = STATUS_INSUFFICIENT_RESOURCES;
1082 }
1083
1084 if (Endpoint->HeaderBuffer && HeaderBuffer)
1085 {
1086 Endpoint->EndpointProperties.BufferVA = HeaderBuffer->VirtualAddress;
1087 Endpoint->EndpointProperties.BufferPA = HeaderBuffer->PhysicalAddress;
1088 Endpoint->EndpointProperties.BufferLength = HeaderBuffer->BufferLength;
1089 }
1090
1091 if (NT_SUCCESS(Status))
1092 {
1093 MiniportOpenEndpoint(FdoDevice, Endpoint);
1094
1095 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
1096 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
1097
1098 if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
1099 {
1100 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1101
1102 Packet->SetEndpointState(FdoExtension->MiniPortExt,
1103 Endpoint + 1,
1104 USBPORT_ENDPOINT_ACTIVE);
1105
1106 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1107 }
1108
1109 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1110 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
1111 }
1112
1113 InterlockedDecrement(&Endpoint->LockCounter);
1114
1115 return Status;
1116 }
1117
1118 VOID
1119 NTAPI
1120 USBPORT_FlushClosedEndpointList(IN PDEVICE_OBJECT FdoDevice)
1121 {
1122 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1123 KIRQL OldIrql;
1124 PLIST_ENTRY ClosedList;
1125 PUSBPORT_ENDPOINT Endpoint;
1126
1127 DPRINT("USBPORT_FlushClosedEndpointList: ... \n");
1128
1129 FdoExtension = FdoDevice->DeviceExtension;
1130
1131 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql);
1132 ClosedList = &FdoExtension->EndpointClosedList;
1133
1134 while (!IsListEmpty(ClosedList))
1135 {
1136 Endpoint = CONTAINING_RECORD(ClosedList->Flink,
1137 USBPORT_ENDPOINT,
1138 CloseLink);
1139
1140 RemoveHeadList(ClosedList);
1141 Endpoint->CloseLink.Flink = NULL;
1142 Endpoint->CloseLink.Blink = NULL;
1143
1144 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql);
1145
1146 USBPORT_DeleteEndpoint(FdoDevice, Endpoint);
1147
1148 KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql);
1149 }
1150
1151 KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql);
1152 }
1153
1154 VOID
1155 NTAPI
1156 USBPORT_InvalidateEndpointHandler(IN PDEVICE_OBJECT FdoDevice,
1157 IN PUSBPORT_ENDPOINT Endpoint,
1158 IN ULONG Type)
1159 {
1160 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1161 PUSBPORT_REGISTRATION_PACKET Packet;
1162 PLIST_ENTRY Entry;
1163 PLIST_ENTRY WorkerLink;
1164 PUSBPORT_ENDPOINT endpoint;
1165 KIRQL OldIrql;
1166 BOOLEAN IsAddEntry = FALSE;
1167
1168 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: Endpoint - %p, Type - %x\n",
1169 Endpoint,
1170 Type);
1171
1172 FdoExtension = FdoDevice->DeviceExtension;
1173 Packet = &FdoExtension->MiniPortInterface->Packet;
1174
1175 if (Endpoint)
1176 {
1177 WorkerLink = &Endpoint->WorkerLink;
1178 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
1179 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: KeAcquireSpinLock \n");
1180
1181 if ((!WorkerLink->Flink || !WorkerLink->Blink) &&
1182 !(Endpoint->Flags & ENDPOINT_FLAG_IDLE) &&
1183 USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED)
1184 {
1185 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n");
1186 InsertTailList(&FdoExtension->WorkerList, WorkerLink);
1187 IsAddEntry = TRUE;
1188 }
1189
1190 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
1191
1192 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1193 Type = INVALIDATE_ENDPOINT_WORKER_THREAD;
1194 }
1195 else
1196 {
1197 KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
1198
1199 Entry = &FdoExtension->EndpointList;
1200
1201 while (Entry && Entry != &FdoExtension->EndpointList)
1202 {
1203 endpoint = CONTAINING_RECORD(Entry,
1204 USBPORT_ENDPOINT,
1205 EndpointLink);
1206
1207 if (!endpoint->WorkerLink.Flink || !endpoint->WorkerLink.Blink)
1208 {
1209 if (!(endpoint->Flags & ENDPOINT_FLAG_IDLE) &&
1210 !(endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) &&
1211 USBPORT_GetEndpointState(endpoint) != USBPORT_ENDPOINT_CLOSED)
1212 {
1213 DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n");
1214 InsertTailList(&FdoExtension->WorkerList, &endpoint->WorkerLink);
1215 IsAddEntry = TRUE;
1216 }
1217 }
1218
1219 Entry = endpoint->EndpointLink.Flink;
1220 }
1221
1222 KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
1223 }
1224
1225 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
1226 {
1227 Type = INVALIDATE_ENDPOINT_WORKER_THREAD;
1228 }
1229 else if (IsAddEntry == FALSE && Type == INVALIDATE_ENDPOINT_INT_NEXT_SOF)
1230 {
1231 Type = INVALIDATE_ENDPOINT_ONLY;
1232 }
1233
1234 switch (Type)
1235 {
1236 case INVALIDATE_ENDPOINT_WORKER_THREAD:
1237 USBPORT_SignalWorkerThread(FdoDevice);
1238 break;
1239
1240 case INVALIDATE_ENDPOINT_WORKER_DPC:
1241 KeInsertQueueDpc(&FdoExtension->WorkerRequestDpc, NULL, NULL);
1242 break;
1243
1244 case INVALIDATE_ENDPOINT_INT_NEXT_SOF:
1245 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1246 Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
1247 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1248 break;
1249 }
1250 }
1251
1252 ULONG
1253 NTAPI
1254 USBPORT_DmaEndpointPaused(IN PDEVICE_OBJECT FdoDevice,
1255 IN PUSBPORT_ENDPOINT Endpoint)
1256 {
1257 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1258 PUSBPORT_REGISTRATION_PACKET Packet;
1259 PLIST_ENTRY Entry;
1260 PUSBPORT_TRANSFER Transfer;
1261 PURB Urb;
1262 ULONG Frame;
1263 ULONG CurrentFrame;
1264 ULONG CompletedLen = 0;
1265 KIRQL OldIrql;
1266
1267 DPRINT_CORE("USBPORT_DmaEndpointPaused \n");
1268
1269 FdoExtension = FdoDevice->DeviceExtension;
1270 Packet = &FdoExtension->MiniPortInterface->Packet;
1271
1272 Entry = Endpoint->TransferList.Flink;
1273
1274 if (Entry == &Endpoint->TransferList)
1275 return USBPORT_ENDPOINT_ACTIVE;
1276
1277 while (Entry && Entry != &Endpoint->TransferList)
1278 {
1279 Transfer = CONTAINING_RECORD(Entry,
1280 USBPORT_TRANSFER,
1281 TransferLink);
1282
1283 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED))
1284 {
1285 if (Transfer->Flags & TRANSFER_FLAG_ISO &&
1286 Transfer->Flags & TRANSFER_FLAG_SUBMITED &&
1287 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1288 {
1289 Urb = Transfer->Urb;
1290
1291 Frame = Urb->UrbIsochronousTransfer.StartFrame +
1292 Urb->UrbIsochronousTransfer.NumberOfPackets;
1293
1294 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1295 CurrentFrame = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
1296 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1297
1298 if (Frame + 1 > CurrentFrame)
1299 {
1300 return USBPORT_GetEndpointState(Endpoint);
1301 }
1302 }
1303
1304 if ((Transfer->Flags & TRANSFER_FLAG_SUBMITED) &&
1305 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1306 {
1307 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1308
1309 Packet->AbortTransfer(FdoExtension->MiniPortExt,
1310 Endpoint + 1,
1311 Transfer->MiniportTransfer,
1312 &CompletedLen);
1313
1314 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1315
1316 if (Transfer->Flags & TRANSFER_FLAG_ISO)
1317 {
1318 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_FlushIsoTransfer\n");
1319 ASSERT(FALSE); //USBPORT_FlushIsoTransfer();
1320 }
1321 else
1322 {
1323 Transfer->CompletedTransferLen = CompletedLen;
1324 }
1325 }
1326
1327 RemoveEntryList(&Transfer->TransferLink);
1328 Entry = Transfer->TransferLink.Flink;
1329
1330 if (Transfer->Flags & TRANSFER_FLAG_SPLITED)
1331 {
1332 USBPORT_CancelSplitTransfer(Transfer);
1333 }
1334 else
1335 {
1336 InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
1337 }
1338 }
1339 else
1340 {
1341 Entry = Transfer->TransferLink.Flink;
1342 }
1343 }
1344
1345 return USBPORT_ENDPOINT_ACTIVE;
1346 }
1347
1348 ULONG
1349 NTAPI
1350 USBPORT_DmaEndpointActive(IN PDEVICE_OBJECT FdoDevice,
1351 IN PUSBPORT_ENDPOINT Endpoint)
1352 {
1353 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1354 PUSBPORT_REGISTRATION_PACKET Packet;
1355 PLIST_ENTRY Entry;
1356 PUSBPORT_TRANSFER Transfer;
1357 LARGE_INTEGER TimeOut;
1358 MPSTATUS MpStatus;
1359 KIRQL OldIrql;
1360
1361 DPRINT_CORE("USBPORT_DmaEndpointActive \n");
1362
1363 FdoExtension = FdoDevice->DeviceExtension;
1364
1365 Entry = Endpoint->TransferList.Flink;
1366
1367 while (Entry && Entry != &Endpoint->TransferList)
1368 {
1369 Transfer = CONTAINING_RECORD(Entry,
1370 USBPORT_TRANSFER,
1371 TransferLink);
1372
1373 if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED) &&
1374 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1375 {
1376 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1377
1378 Packet = &FdoExtension->MiniPortInterface->Packet;
1379
1380 if (Transfer->Flags & TRANSFER_FLAG_ISO)
1381 {
1382 DPRINT1("USBPORT_DmaEndpointActive: FIXME call SubmitIsoTransfer\n");
1383
1384 MpStatus = Packet->SubmitIsoTransfer(FdoExtension->MiniPortExt,
1385 Endpoint + 1,
1386 &Transfer->TransferParameters,
1387 Transfer->MiniportTransfer,
1388 NULL);//&Transfer->IsoTransferParameters);
1389 }
1390 else
1391 {
1392 MpStatus = Packet->SubmitTransfer(FdoExtension->MiniPortExt,
1393 Endpoint + 1,
1394 &Transfer->TransferParameters,
1395 Transfer->MiniportTransfer,
1396 &Transfer->SgList);
1397 }
1398
1399 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1400
1401 if (MpStatus)
1402 {
1403 if ((MpStatus != MP_STATUS_FAILURE) && Transfer->Flags & TRANSFER_FLAG_ISO)
1404 {
1405 DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_ErrorCompleteIsoTransfer\n");
1406 ASSERT(FALSE); //USBPORT_ErrorCompleteIsoTransfer();
1407 }
1408
1409 return USBPORT_ENDPOINT_ACTIVE;
1410 }
1411
1412 Transfer->Flags |= TRANSFER_FLAG_SUBMITED;
1413 KeQuerySystemTime(&Transfer->Time);
1414
1415 TimeOut.QuadPart = 10000 * Transfer->TimeOut;
1416 Transfer->Time.QuadPart += TimeOut.QuadPart;
1417 }
1418
1419 if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED))
1420 {
1421 return USBPORT_ENDPOINT_PAUSED;
1422 }
1423
1424 Entry = Transfer->TransferLink.Flink;
1425 }
1426
1427 return USBPORT_ENDPOINT_ACTIVE;
1428 }
1429
1430 VOID
1431 NTAPI
1432 USBPORT_DmaEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint)
1433 {
1434 PDEVICE_OBJECT FdoDevice;
1435 ULONG PrevState;
1436 ULONG EndpointState;
1437 BOOLEAN IsPaused = FALSE;
1438
1439 DPRINT_CORE("USBPORT_DmaEndpointWorker ... \n");
1440
1441 FdoDevice = Endpoint->FdoDevice;
1442
1443 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
1444
1445 PrevState = USBPORT_GetEndpointState(Endpoint);
1446
1447 if (PrevState == USBPORT_ENDPOINT_PAUSED)
1448 {
1449 EndpointState = USBPORT_DmaEndpointPaused(FdoDevice, Endpoint);
1450 }
1451 else if (PrevState == USBPORT_ENDPOINT_ACTIVE)
1452 {
1453 EndpointState = USBPORT_DmaEndpointActive(FdoDevice, Endpoint);
1454 }
1455 else
1456 {
1457 #ifndef NDEBUG_USBPORT_CORE
1458 DPRINT1("USBPORT_DmaEndpointWorker: DbgBreakPoint. EndpointState - %x\n",
1459 EndpointState);
1460 DbgBreakPoint();
1461 #endif
1462 EndpointState = USBPORT_ENDPOINT_UNKNOWN;
1463 }
1464
1465 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
1466
1467 USBPORT_FlushCancelList(Endpoint);
1468
1469 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
1470
1471 if (EndpointState == PrevState)
1472 {
1473 if (EndpointState == USBPORT_ENDPOINT_PAUSED)
1474 {
1475 IsPaused = TRUE;
1476 }
1477 }
1478 else
1479 {
1480 USBPORT_SetEndpointState(Endpoint, EndpointState);
1481 }
1482
1483 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
1484
1485 if (IsPaused)
1486 {
1487 USBPORT_InvalidateEndpointHandler(FdoDevice,
1488 Endpoint,
1489 INVALIDATE_ENDPOINT_WORKER_THREAD);
1490 }
1491
1492 DPRINT_CORE("USBPORT_DmaEndpointWorker exit \n");
1493 }
1494
1495 BOOLEAN
1496 NTAPI
1497 USBPORT_EndpointWorker(IN PUSBPORT_ENDPOINT Endpoint,
1498 IN BOOLEAN LockNotChecked)
1499 {
1500 PDEVICE_OBJECT FdoDevice;
1501 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1502 PUSBPORT_REGISTRATION_PACKET Packet;
1503 ULONG EndpointState;
1504
1505 DPRINT_CORE("USBPORT_EndpointWorker: Endpoint - %p, LockNotChecked - %x\n",
1506 Endpoint,
1507 LockNotChecked);
1508
1509 FdoDevice = Endpoint->FdoDevice;
1510 FdoExtension = FdoDevice->DeviceExtension;
1511 Packet = &FdoExtension->MiniPortInterface->Packet;
1512
1513 if (LockNotChecked == FALSE)
1514 {
1515 if (InterlockedIncrement(&Endpoint->LockCounter))
1516 {
1517 InterlockedDecrement(&Endpoint->LockCounter);
1518 DPRINT_CORE("USBPORT_EndpointWorker: LockCounter > 0\n");
1519 return TRUE;
1520 }
1521 }
1522
1523 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1524
1525 KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
1526
1527 if (USBPORT_GetEndpointState(Endpoint) == USBPORT_ENDPOINT_CLOSED)
1528 {
1529 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
1530 InterlockedDecrement(&Endpoint->LockCounter);
1531 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_CLOSED. return FALSE\n");
1532 return FALSE;
1533 }
1534
1535 if ((Endpoint->Flags & (ENDPOINT_FLAG_ROOTHUB_EP0 | ENDPOINT_FLAG_NUKE)) == 0)
1536 {
1537 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1538 Packet->PollEndpoint(FdoExtension->MiniPortExt, Endpoint + 1);
1539 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1540 }
1541
1542 EndpointState = USBPORT_GetEndpointState(Endpoint);
1543
1544 if (EndpointState == USBPORT_ENDPOINT_REMOVE)
1545 {
1546 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
1547 Endpoint->StateLast = USBPORT_ENDPOINT_CLOSED;
1548 Endpoint->StateNext = USBPORT_ENDPOINT_CLOSED;
1549 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1550
1551 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
1552
1553 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
1554
1555 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList,
1556 &Endpoint->CloseLink,
1557 &FdoExtension->EndpointClosedSpinLock);
1558
1559 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1560
1561 InterlockedDecrement(&Endpoint->LockCounter);
1562 DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_REMOVE. return FALSE\n");
1563 return FALSE;
1564 }
1565
1566 if (!IsListEmpty(&Endpoint->PendingTransferList) ||
1567 !IsListEmpty(&Endpoint->TransferList) ||
1568 !IsListEmpty(&Endpoint->CancelList))
1569 {
1570 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
1571
1572 EndpointState = USBPORT_GetEndpointState(Endpoint);
1573
1574 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
1575 if (EndpointState == Endpoint->StateNext)
1576 {
1577 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1578
1579 if (Endpoint->EndpointWorker)
1580 {
1581 USBPORT_DmaEndpointWorker(Endpoint);
1582 }
1583 else
1584 {
1585 USBPORT_RootHubEndpointWorker(Endpoint);
1586 }
1587
1588 USBPORT_FlushAbortList(Endpoint);
1589
1590 InterlockedDecrement(&Endpoint->LockCounter);
1591 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n");
1592 return FALSE;
1593 }
1594
1595 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1596 InterlockedDecrement(&Endpoint->LockCounter);
1597
1598 DPRINT_CORE("USBPORT_EndpointWorker: return TRUE\n");
1599 return TRUE;
1600 }
1601
1602 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
1603
1604 USBPORT_FlushAbortList(Endpoint);
1605
1606 InterlockedDecrement(&Endpoint->LockCounter);
1607 DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n");
1608 return FALSE;
1609 }