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