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