Transfers data over an isochronous pipe as soon as possible (ASAP).
#define MAX_OUTSTANDING_TRANSFERS 3
#define MAX_TRANSFERS_TOTAL 64
#define ISO_PACKETS_PER_TRANSFER (8)
UINT gIntfIndex = UINT_MAX;
UINT gAltfSetting = UINT_MAX;
UINT gEpID = UINT_MAX;
typedef struct _MY_ISO_BUFFER_EL
{
PUCHAR TransferBuffer;
UINT FrameNumber;
struct _MY_ISO_BUFFER_EL* prev;
struct _MY_ISO_BUFFER_EL* next;
} MY_ISO_BUFFER_EL, * PMY_ISO_BUFFER_EL;
typedef struct _MY_ISO_XFERS
{
ULONG TransferBufferSize;
PMY_ISO_BUFFER_EL Outstanding;
PMY_ISO_BUFFER_EL Completed;
ULONG SubmittedCount;
ULONG CompletedCount;
} MY_ISO_XFERS, * PMY_ISO_XFERS;
MY_ISO_XFERS gXfers;
DATA_COUNTER_STATS Dcs;
FILE* gOutFile = NULL;
int write_output(FILE* const stream, const char* fmt, ...)
{
int len;
va_list args;
va_start(args, fmt);
if (stream)
{
len = vfprintf(stream, fmt, args);
}
else
{
len = vprintf(fmt, args);
}
va_end(args);
return len;
}
VOID IsoXferComplete(PMY_ISO_XFERS myXfers, PMY_ISO_BUFFER_EL myBufferEL, ULONG transferLength)
{
int packetPos;
UINT goodPackets, badPackets;
char packetCounters[ISO_PACKETS_PER_TRANSFER * 3 + 1];
goodPackets = 0;
badPackets = 0;
{
transferLength = 0;
for (packetPos = 0; packetPos < ISO_PACKETS_PER_TRANSFER; packetPos++)
{
UINT offset, length, status;
sprintf(&packetCounters[packetPos * 3], "%02X ", myBufferEL->TransferBuffer[offset + 1]);
if (status == 0 && length != 0)
{
goodPackets++;
transferLength += length;
}
else
{
badPackets++;
}
}
}
else
{
transferLength = gXfers.TransferBufferSize;
}
Dcs.TotalBytes = 0;
mDcs_MarkStop(&Dcs, transferLength);
{
if (myXfers->CompletedCount > 0)
{
write_output(gOutFile,
"#%u: TransferLength=%u GoodPackets=%u, BadPackets=%u, BPS-average:%.2f\n\t%s\n",
myXfers->CompletedCount, transferLength, goodPackets, badPackets, Dcs.Bps, packetCounters);
}
else
{
write_output(gOutFile,
"#%u: TransferLength=%u GoodPackets=%u, BadPackets=%u, BPS-average:unknown\n\t%s\n",
myXfers->CompletedCount, transferLength, goodPackets, badPackets, packetCounters);
}
}
else
{
write_output(gOutFile,
"#%u: TransferLength=%u\n",
myXfers->CompletedCount, transferLength);
}
Dcs.Start = Dcs.Stop;
myXfers->CompletedCount++;
}
int __cdecl main(int argc, char* argv[])
{
DWORD errorCode = ERROR_SUCCESS;
UCHAR interfaceIndex;
BOOL success;
UINT deviceSpeedLength;
BYTE deviceSpeed;
PMY_ISO_BUFFER_EL nextBufferEL;
PMY_ISO_BUFFER_EL nextBufferELTemp;
ULONG transferred;
BYTE bTemp;
char logFilename[128];
UINT logFilenameLength;
memset(&gXfers, 0, sizeof(gXfers));
memset(&gInterfaceDescriptor, 0, sizeof(gInterfaceDescriptor));
memset(&gPipeInfo, 0, sizeof(gPipeInfo));
return GetLastError();
Examples_GetArgVal(argc, argv, "intf=", &gIntfIndex, FALSE);
Examples_GetArgVal(argc, argv, "altf=", &gAltfSetting, TRUE);
Examples_GetArgVal(argc, argv, "ep=", &gEpID, TRUE);
logFilenameLength = sizeof(logFilename) - 1;
if (Examples_GetArgStr(argc, argv, "logfile", logFilename, &logFilenameLength))
gOutFile = fopen(logFilename, "w");
{
errorCode = GetLastError();
printf("LibK_LoadDriverAPI failed. ErrorCode: %08lXh\n", errorCode);
goto Done;
}
{
errorCode = ERROR_NOT_SUPPORTED;
printf(
"DriverID %i does not support isochronous transfers using 'Isoch' functions. ErrorCode: %08lXh\n", Usb.
Info.
DriverID, errorCode);
goto Done;
}
if (!Usb.
Init(&usbHandle, deviceInfo))
{
errorCode = GetLastError();
printf("Usb.Init failed. ErrorCode: %08lXh\n", errorCode);
goto Done;
}
printf("Device opened successfully!\n");
interfaceIndex = (UCHAR)-1;
memset(&gInterfaceDescriptor, 0, sizeof(gInterfaceDescriptor));
memset(&gPipeInfo, 0, sizeof(gPipeInfo));
while (Usb.
SelectInterface(usbHandle, ++interfaceIndex, TRUE))
{
if (gIntfIndex != UINT_MAX && gIntfIndex != interfaceIndex) continue;
memset(&gInterfaceDescriptor, 0, sizeof(gInterfaceDescriptor));
memset(&gPipeInfo, 0, sizeof(gPipeInfo));
UCHAR gAltsettingIndex = (UCHAR)-1;
while (Usb.
QueryInterfaceSettings(usbHandle, ++gAltsettingIndex, &gInterfaceDescriptor))
{
if (gAltfSetting == UINT_MAX || gAltfSetting == gInterfaceDescriptor.
bAlternateSetting)
{
UCHAR pipeIndex = (UCHAR)-1;
while (Usb.
QueryPipeEx(usbHandle, gAltsettingIndex, ++pipeIndex, &gPipeInfo))
{
{
if (gEpID == UINT_MAX)
break;
if ((gEpID == 0) && (gPipeInfo.
PipeId & 0x80) == 0)
{
break;
}
if ((gEpID == 0x80) && (gPipeInfo.
PipeId & 0x80) == 0x80)
{
break;
}
if (gEpID == gPipeInfo.
PipeId)
{
break;
}
}
}
memset(&gPipeInfo, 0, sizeof(gPipeInfo));
}
memset(&gInterfaceDescriptor, 0, sizeof(gInterfaceDescriptor));
}
}
{
printf("Pipe not found.\n");
goto Done;
}
{
printf("Pipe does not have MaximumBytesPerInterval.\n");
goto Done;
}
success = Usb.
SetAltInterface(
usbHandle,
FALSE,
if (!success)
{
printf("Usb.SetAltInterface failed.\n");
goto Done;
}
deviceSpeedLength = 1;
success = Usb.
QueryDeviceInformation(usbHandle, DEVICE_SPEED, &deviceSpeedLength, &deviceSpeed);
if (!success)
{
printf("Usb.QueryDeviceInformation failed.\n");
goto Done;
}
bTemp = TRUE;
Usb.
SetPipePolicy(usbHandle, gPipeInfo.
PipeId, ISO_ALWAYS_START_ASAP, 1, &bTemp);
if (!success)
{
printf("IsochK_CalcPacketInformation failed.\n");
goto Done;
}
success = Bench_Configure(usbHandle, BM_COMMAND_SET_TEST, 0, &Usb, &testType);
if (!success)
{
errorCode = GetLastError();
printf("Bench_Configure failed. ErrorCode: %08lXh\n", errorCode);
goto Done;
}
printf("Device hardware fully prepared..\n");
write_output(gOutFile,
"XFER-ISO TEST\n", deviceInfo->
DeviceID);
write_output(gOutFile, "----------------------------------------------------------\n");
write_output(gOutFile,
"Device ID : %s\n", deviceInfo->
DeviceID);
write_output(gOutFile,
"Device Name : %s\n", deviceInfo->
DeviceDesc);
write_output(gOutFile,
"Interface : %u\n", gInterfaceDescriptor.
bInterfaceNumber);
write_output(gOutFile,
"Alt Setting : %u\n", gInterfaceDescriptor.
bAlternateSetting);
write_output(gOutFile,
"Pipe ID : 0x%02X (%s)\n", gPipeInfo.
PipeId, (gPipeInfo.
PipeId & 0x80) ?
"Read" :
"Write");
write_output(gOutFile, "\n");
do
{
int pos;
success =
OvlK_Init(&gXfers.OvlPool, usbHandle, MAX_OUTSTANDING_TRANSFERS, KOVL_POOL_FLAG_NONE);
if (!success)
{
errorCode = GetLastError();
printf("OvlK_Init Failed.\n");
goto Done;
}
for (pos = 0; pos < MAX_OUTSTANDING_TRANSFERS; pos++)
{
nextBufferEL = malloc(sizeof(MY_ISO_BUFFER_EL));
if (nextBufferEL != NULL)
{
memset(nextBufferEL, 0, sizeof(nextBufferEL[0]));
nextBufferEL->TransferBuffer = malloc(gXfers.TransferBufferSize);
if (!
IsochK_Init(&nextBufferEL->IsoHandle, usbHandle, gPipeInfo.
PipeId, ISO_PACKETS_PER_TRANSFER, nextBufferEL->TransferBuffer, gXfers.TransferBufferSize))
{
errorCode = GetLastError();
printf("IsochK_Init Failed.\n");
goto Done;
}
{
errorCode = GetLastError();
printf("IsochK_SetPacketOffsets Failed.\n");
goto Done;
}
if (!
OvlK_Acquire(&nextBufferEL->OvlHandle, gXfers.OvlPool))
{
errorCode = GetLastError();
printf("OvlK_Acquire Failed.\n");
goto Done;
}
}
}
} while (0);
mDcs_Init(&Dcs);
do
{
while (errorCode == ERROR_SUCCESS && gXfers.Completed && gXfers.SubmittedCount < MAX_TRANSFERS_TOTAL)
{
nextBufferEL = gXfers.Completed;
Usb.
IsochReadPipe(nextBufferEL->IsoHandle, gXfers.TransferBufferSize, NULL, ISO_PACKETS_PER_TRANSFER, nextBufferEL->OvlHandle);
else
Usb.
IsochWritePipe(nextBufferEL->IsoHandle, gXfers.TransferBufferSize, NULL, ISO_PACKETS_PER_TRANSFER, nextBufferEL->OvlHandle);
errorCode = GetLastError();
if (errorCode != ERROR_IO_PENDING)
{
printf("Usb.IsochReadPipe failed. ErrorCode: %08lXh\n", errorCode);
goto Done;
}
gXfers.SubmittedCount++;
errorCode = ERROR_SUCCESS;
}
nextBufferEL = gXfers.Outstanding;
if (!nextBufferEL)
{
printf("Done!\n");
goto Done;
}
success = Usb.
GetOverlappedResult(usbHandle, nextBufferEL->OvlHandle, &transferred, TRUE);
if (!success)
{
errorCode = GetLastError();
printf("OvlK_Wait failed. ErrorCode: %08lXh\n", errorCode);
goto Done;
}
IsoXferComplete(&gXfers, nextBufferEL, transferred);
} while (errorCode == ERROR_SUCCESS);
Done:
{
}
{
free(nextBufferEL->TransferBuffer);
free(nextBufferEL);
}
if (gOutFile)
{
fflush(gOutFile);
fclose(gOutFile);
gOutFile = NULL;
}
return errorCode;
}