Skip to content

Commit 1bf6579

Browse files
committed
[USBEHCI][USBPORT]
- Fix returning data length of iso packet
1 parent e61329e commit 1bf6579

3 files changed

Lines changed: 60 additions & 71 deletions

File tree

drivers/usb/usbehci/usbehci.c

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,6 +2703,7 @@ EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,
27032703
if (PacketsThisITD > PacketsPerITD)
27042704
PacketsThisITD = PacketsPerITD;
27052705
ASSERT(PacketsThisITD <= 8);
2706+
ASSERT(PacketsThisITD > 0);
27062707

27072708
/* Setup buffer page 0 with device/endpoint info */
27082709
ITD->HwTD.Buffer[0].DeviceAddress = DeviceAddress;
@@ -2718,6 +2719,9 @@ EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,
27182719
ASSERT(ITD->HwTD.Buffer[2].Multi > 0);
27192720
ASSERT(ITD->HwTD.Buffer[2].Multi <= 3);
27202721

2722+
// store number of packets
2723+
ITD->PacketsThisITD = PacketsThisITD;
2724+
27212725
/* Program each packet into a transaction slot */
27222726
for (p = 0; p < PacketsThisITD; p++)
27232727
{
@@ -2727,6 +2731,9 @@ EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,
27272731
ULONG Offset;
27282732
ULONG ThisPageSelect;
27292733

2734+
/* store USBPORT iso packet ref*/
2735+
ITD->IsoPacket[p] = Packet;
2736+
27302737
/* Determine microframe slot: for period=1, slots 0,1,2,...7 */
27312738
MicroFrame = p * Period;
27322739

@@ -2792,7 +2799,7 @@ EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,
27922799
ITD->HwTD.Transaction[MicroFrame].xOffset = Offset;
27932800
ITD->HwTD.Transaction[MicroFrame].PageSelect = ThisPageSelect;
27942801
ITD->HwTD.Transaction[MicroFrame].xLength = Packet->PacketLength;
2795-
ITD->HwTD.Transaction[MicroFrame].Status = EHCI_TOKEN_STATUS_ACTIVE >> 4;
2802+
ITD->HwTD.Transaction[MicroFrame].Status = 1 << 3;
27962803

27972804
/* Set IOC on the last transaction of the last iTD */
27982805
if (p == PacketsThisITD - 1)
@@ -2823,22 +2830,11 @@ EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,
28232830
KeMemoryBarrier();
28242831
/* Store the frame index in the iTD for unlinking later */
28252832
ITD->ScheduledFrame = FrameIndex;
2826-
/* clear next itd software link */
2827-
ITD->NextHcdTD = NULL;
28282833

28292834
/* Track which frame this iTD was inserted at */
28302835
if (ITDCount == 0)
28312836
EhciEndpoint->StartingFrame = FrameIndex;
28322837

2833-
if (!FirstITD)
2834-
{
2835-
FirstITD = ITD;
2836-
}
2837-
if (LastITD)
2838-
{
2839-
LastITD->NextHcdTD = ITD;
2840-
}
2841-
LastITD = ITD;
28422838
PacketIndex += PacketsThisITD;
28432839
CurrentFrame++;
28442840
ITDCount++;
@@ -3917,18 +3913,18 @@ EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension,
39173913
ITD = (PEHCI_HCD_ITD)((ULONG_PTR)ITD + Size);
39183914
continue;
39193915
}
3920-
3916+
KeMemoryBarrier();
39213917
/* Check if any initialized transaction in this iTD is still active.
39223918
* Also verify at least one transaction was programmed to avoid
39233919
* false-completing an allocated but not-yet-programmed iTD. */
39243920
StillActive = FALSE;
39253921
BOOLEAN HasProgrammedTransactions = FALSE;
3926-
for (TransIdx = 0; TransIdx < EHCI_MAX_ITD_TRANSACTIONS; TransIdx++)
3922+
ASSERT(ITD->PacketsThisITD);
3923+
for (TransIdx = 0; TransIdx < ITD->PacketsThisITD; TransIdx++)
39273924
{
39283925
if (ITD->PacketLength[TransIdx] > 0)
39293926
{
39303927
HasProgrammedTransactions = TRUE;
3931-
39323928
ULONG Status = ITD->HwTD.Transaction[TransIdx].Status;
39333929
if (Status & (1 << 3))
39343930
{
@@ -3937,7 +3933,7 @@ EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension,
39373933
}
39383934
}
39393935
}
3940-
3936+
KeMemoryBarrier();
39413937
if (HasProgrammedTransactions && !StillActive)
39423938
{
39433939
/* All programmed transactions completed, process this iTD */
@@ -4397,8 +4393,12 @@ EHCI_ProcessCompletedITD(IN PEHCI_EXTENSION EhciExtension,
43974393
if (!EhciTransfer || !EhciEndpoint)
43984394
return;
43994395

4396+
/* make sure we are in sync */
4397+
KeMemoryBarrier();
4398+
44004399
/* Check all transactions in the iTD */
4401-
for (TransactionIndex = 0; TransactionIndex < EHCI_MAX_ITD_TRANSACTIONS; TransactionIndex++)
4400+
ASSERT(ITD->PacketsThisITD);
4401+
for (TransactionIndex = 0; TransactionIndex < ITD->PacketsThisITD; TransactionIndex++)
44024402
{
44034403
/* Use PacketLength[] (original programmed length) to detect used transactions.
44044404
* The hardware xLength field contains REMAINING bytes after transfer, so a
@@ -4408,7 +4408,7 @@ EHCI_ProcessCompletedITD(IN PEHCI_EXTENSION EhciExtension,
44084408
{
44094409
ULONG Status = ITD->HwTD.Transaction[TransactionIndex].Status;
44104410
ULONG Remaining = ITD->HwTD.Transaction[TransactionIndex].xLength;
4411-
4411+
ULONG Completed;
44124412
if ((Status & (1 << 3))) //EHCI_TOKEN_STATUS_ACTIVE >> 4))
44134413
{
44144414
/* Transaction still active, not complete yet */
@@ -4421,20 +4421,27 @@ EHCI_ProcessCompletedITD(IN PEHCI_EXTENSION EhciExtension,
44214421
ASSERT((Status & (1 << 1)) == 0);
44224422

44234423
/* Transaction completed - bytes transferred = programmed - remaining */
4424-
TotalBytesTransferred += ITD->PacketLength[TransactionIndex] - Remaining;
4424+
Completed = ITD->PacketLength[TransactionIndex] - Remaining;
4425+
TotalBytesTransferred += Completed;
44254426

44264427
/* Check for errors (bit 2 = Transaction Error in 4-bit status) */
44274428
if (Status & 0x04)
44284429
{
44294430
DPRINT1("EHCI_ProcessCompletedITD: Transaction %d error, status 0x%x\n",
44304431
TransactionIndex, Status);
44314432
EhciTransfer->USBDStatus = USBD_STATUS_XACT_ERROR;
4433+
ITD->IsoPacket[TransactionIndex]->CompletionStatus = USBD_STATUS_XACT_ERROR;
4434+
}
4435+
else
4436+
{
4437+
ITD->IsoPacket[TransactionIndex]->CompletionStatus = USBD_STATUS_SUCCESS;
4438+
ITD->IsoPacket[TransactionIndex]->BytesTransferred = Completed;
44324439
}
4433-
44344440
ITD->PacketStatus[TransactionIndex] = Status;
44354441
}
44364442
}
44374443
}
4444+
KeMemoryBarrier();
44384445

44394446
if (TransferComplete)
44404447
{
@@ -4443,14 +4450,15 @@ EHCI_ProcessCompletedITD(IN PEHCI_EXTENSION EhciExtension,
44434450

44444451
/* Remove iTD from frame list */
44454452
EHCI_UnlinkITDFromFrameList(EhciExtension, ITD, ITD->ScheduledFrame, EhciTransfer);
4446-
4447-
/* Mark iTD as free */
4448-
ITD->TdFlags &= ~EHCI_HCD_ITD_FLAG_ALLOCATED;
4449-
ITD->NextHcdTD = NULL;
44504453
ITD->EhciTransfer = NULL;
44514454
ITD->EhciEndpoint = NULL;
44524455
for(ULONG Index = 0; Index < EHCI_MAX_ITD_TRANSACTIONS; Index++)
4456+
{
44534457
ITD->PacketLength[Index] = 0;
4458+
ITD->IsoPacket[Index] = NULL;
4459+
}
4460+
/* Mark iTD as free */
4461+
ITD->TdFlags &= ~EHCI_HCD_ITD_FLAG_ALLOCATED;
44544462

44554463
EhciEndpoint->RemainITDs++;
44564464

@@ -4508,9 +4516,13 @@ EHCI_UnlinkITDFromFrameList(IN PEHCI_EXTENSION EhciExtension,
45084516
DPRINT_EHCI("EHCI_UnlinkITDFromFrameList: Unlinked iTD from frame %d head\n", FrameIndex);
45094517
KeMemoryBarrier();
45104518
}
4519+
else
4520+
{
4521+
// LINKING ERROR
4522+
ASSERT(FALSE);
4523+
}
45114524
RemoveEntryList(&ITD->ActiveITDEntry);
45124525
RtlClearBits(&EhciExtension->IsoBitmap, ITD->ScheduledFrame, 1);
4513-
ITD->NextHcdTD = NULL;
45144526
ITD->EhciTransfer = NULL;
45154527
}
45164528

drivers/usb/usbehci/usbehci.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,17 @@ typedef struct _EHCI_HCD_ITD {
104104
ULONG TdFlags;
105105
struct _EHCI_ENDPOINT * EhciEndpoint;
106106
struct _EHCI_TRANSFER * EhciTransfer;
107-
struct _EHCI_HCD_ITD * NextHcdTD;
108107
ULONG PacketLength[EHCI_MAX_ITD_TRANSACTIONS];
109108
ULONG PacketStatus[EHCI_MAX_ITD_TRANSACTIONS];
110109
LIST_ENTRY ActiveITDEntry;
111110
LIST_ENTRY DoneLink;
111+
PUSBPORT_ISO_PACKET_DATA IsoPacket[EHCI_MAX_ITD_TRANSACTIONS];
112112
ULONG ScheduledFrame; /* Frame list index where this iTD was inserted */
113+
ULONG PacketsThisITD;
113114
#ifdef _WIN64
114115
ULONG Pad[16];
115116
#else
116-
ULONG Pad[23];
117+
ULONG Pad[15];
117118
#endif
118119
} EHCI_HCD_ITD, *PEHCI_HCD_ITD;
119120
C_ASSERT(sizeof(EHCI_HCD_ITD) == ROUND_UP(sizeof(EHCI_HCD_ITD), 32));

drivers/usb/usbport/iso.c

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,11 @@ USBPORT_CompleteIsoTransfer(IN PVOID MiniPortExtension,
218218
{
219219
PUSBPORT_ENDPOINT Endpoint;
220220
PUSBPORT_TRANSFER Transfer;
221+
PUSBPORT_ISO_TRANSFER_DATA IsoBlock;
221222
struct _URB_ISOCH_TRANSFER *IsoUrb;
222-
USBD_ISO_PACKET_DESCRIPTOR *PacketDescriptor, * NextPacketDescriptor;
223-
ULONG i, PacketLength;
224-
ULONG CompletedLength = 0;
223+
PUSBPORT_ISO_PACKET_DATA IsoPacketData;
224+
USBD_ISO_PACKET_DESCRIPTOR *PacketDescriptor;
225+
ULONG i;
225226
ULONG RemainingLength = TransferLength;
226227

227228
DPRINT("USBPORT_CompleteIsoTransfer: TransferLength - %lu\n", TransferLength);
@@ -245,6 +246,14 @@ USBPORT_CompleteIsoTransfer(IN PVOID MiniPortExtension,
245246
return 0;
246247
}
247248

249+
250+
IsoBlock = (PUSBPORT_ISO_TRANSFER_DATA)Transfer->IsoBlockPtr;
251+
if (!IsoBlock)
252+
{
253+
DPRINT1("USBPORT_CompleteIsoTransfer: Invalid Transfer or URB\n");
254+
return 0;
255+
}
256+
248257
IsoUrb = (struct _URB_ISOCH_TRANSFER *)Transfer->Urb;
249258

250259
// Validate this is actually an ISO transfer
@@ -255,59 +264,26 @@ USBPORT_CompleteIsoTransfer(IN PVOID MiniPortExtension,
255264
}
256265

257266
// Update packet descriptors with completion status
267+
ASSERT(IsoBlock->TotalPackets == IsoUrb->NumberOfPackets);
258268
i = 0;
259269
do
260270
{
261271
PacketDescriptor = &IsoUrb->IsoPacket[i];
272+
IsoPacketData = &IsoBlock->Packets[i];
262273

263-
if (i + 1 < IsoUrb->NumberOfPackets)
264-
{
265-
NextPacketDescriptor = &IsoUrb->IsoPacket[i+1];
266-
PacketLength = NextPacketDescriptor->Offset - PacketDescriptor->Offset;
267-
}
268-
else
269-
{
270-
/* last packet */
271-
PacketLength = IsoUrb->TransferBufferLength - PacketDescriptor->Offset;
272-
}
273-
274-
if (RemainingLength >= PacketLength)
275-
{
276-
PacketDescriptor->Status = USBD_STATUS_SUCCESS;
277-
PacketDescriptor->Length = PacketLength;
278-
CompletedLength += PacketDescriptor->Length;
279-
RemainingLength -= PacketDescriptor->Length;
280-
}
281-
else
282-
{
283-
PacketDescriptor->Status = USBD_STATUS_SUCCESS;
284-
PacketDescriptor->Length = RemainingLength;
285-
CompletedLength += RemainingLength;
286-
if (RemainingLength > 0)
287-
{
288-
RemainingLength = 0;
289-
i++;
290-
}
291-
break;
292-
}
274+
PacketDescriptor->Status = IsoPacketData->CompletionStatus;
275+
PacketDescriptor->Length = IsoPacketData->BytesTransferred;
276+
DPRINT("Status %x Length %u Index %u\n", PacketDescriptor->Status, PacketDescriptor->Length, i);
293277
}while(i++ < IsoUrb->NumberOfPackets);
294278

295-
// Mark remaining packets as not processed if any
296-
for (; i < IsoUrb->NumberOfPackets; i++)
297-
{
298-
PacketDescriptor = &IsoUrb->IsoPacket[i];
299-
PacketDescriptor->Status = USBD_STATUS_NOT_ACCESSED;
300-
PacketDescriptor->Length = 0;
301-
}
302-
303279
// Complete the transfer
304280
USBPORT_MiniportCompleteTransfer(MiniPortExtension,
305281
MiniPortEndpoint,
306282
TransferParameters,
307283
USBD_STATUS_SUCCESS,
308-
CompletedLength);
284+
TransferLength);
309285

310-
DPRINT("USBPORT_CompleteIsoTransfer: Completed %lu bytes\n", CompletedLength);
311-
return CompletedLength;
286+
DPRINT("USBPORT_CompleteIsoTransfer: Completed %lu bytes\n", TransferLength);
287+
return TransferLength;
312288
}
313289

0 commit comments

Comments
 (0)