f933922e8bbb7c45b8ccdb09ca7414019ded6b0d
[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 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 ULONG TransferParams[2] = {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 TransferParams);
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 = TransferParams[1];
843 }
844
845 if (TransferParams[0])
846 {
847 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
848 TransferParams[0]);
849 }
850 else
851 {
852 HeaderBuffer = NULL;
853 }
854
855 if (HeaderBuffer || (TransferParams[0] == 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 ULONG EndpointRequirements[2] = {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[0])
1021 {
1022 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
1023 EndpointRequirements[0]);
1024 }
1025 else
1026 {
1027 HeaderBuffer = NULL;
1028 }
1029
1030 if (HeaderBuffer || EndpointRequirements[0] == 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 }