#include "examples.h"
#define EP_TX 0x01
#define EP_RX 0x81
#define EP_PACKET_SIZE 64
#define XFER_LENGTH (EP_PACKET_SIZE*16)
#define XFER_TIMEOUT 1000
#define MAX_XFERS 512
#define MAX_PENDING_IO 3
KUSB_DRIVER_API Usb;
static DWORD g_LoopCounter = 0;
static DWORD g_ErrorCode = ERROR_SUCCESS;
KOVL_POOL_HANDLE gOvlPool = NULL;
typedef struct _MY_XFER_EL
{
KOVL_HANDLE Ovl;
UCHAR Buffer[XFER_LENGTH];
DWORD Length;
DWORD ErrorCode;
struct _MY_XFER_EL* prev;
struct _MY_XFER_EL* next;
} MY_XFER_EL;
VOID OnDataNeeded(MY_XFER_EL* xfer, UCHAR PipeID)
{
static DWORD CounterTx = 0;
xfer->Length = XFER_LENGTH;
printf("[Tx-%03u] PipeID=%02Xh Length=%u\n", ++CounterTx, PipeID, xfer->Length);
}
VOID OnDataArrival(MY_XFER_EL* xfer, UCHAR PipeID)
{
static DWORD CounterRx = 0;
printf("[Rx-%03u] PipeID=%02Xh Length=%u\n", ++CounterRx, PipeID, xfer->Length);
}
BOOL Xfer_Submit(KUSB_HANDLE usbHandle,
MY_XFER_EL** AvailList,
MY_XFER_EL** WaitList,
UCHAR PipeID)
{
MY_XFER_EL* move = *AvailList;
DL_DELETE(*AvailList, move);
DL_APPEND(*WaitList, move);
if (!OvlK_Acquire(&move->Ovl, gOvlPool)) return FALSE;
if (USB_ENDPOINT_DIRECTION_IN(PipeID))
{
move->Length = XFER_LENGTH;
Usb.ReadPipe(usbHandle, PipeID, move->Buffer, move->Length, NULL, move->Ovl);
}
else
{
OnDataNeeded(move, PipeID);
Usb.WritePipe(usbHandle, PipeID, move->Buffer, move->Length, NULL, move->Ovl);
}
if ((move->ErrorCode = GetLastError()) != ERROR_IO_PENDING)
{
g_ErrorCode = move->ErrorCode;
printf("Usb.WritePipe failed on pipe-id %02Xh. ErrorCode: %08Xh\n",
PipeID, g_ErrorCode);
g_LoopCounter = MAX_XFERS;
return FALSE;
}
return TRUE;
}
BOOL Xfer_Wait(MY_XFER_EL* PendingList, ULONG Timeout, UCHAR PipeID)
{
if (PendingList->ErrorCode != ERROR_IO_PENDING)
Timeout = 0;
if (!OvlK_WaitAndRelease(PendingList->Ovl, Timeout, &PendingList->Length))
{
if (PendingList->ErrorCode == ERROR_IO_PENDING)
{
g_ErrorCode = PendingList->ErrorCode = GetLastError();
printf("Failed getting i/o results. ErrorCode: %08Xh\n", g_ErrorCode);
g_LoopCounter = MAX_XFERS;
}
return FALSE;
}
if (USB_ENDPOINT_DIRECTION_IN(PipeID))
{
OnDataArrival(PendingList, PipeID);
}
return TRUE;
}
VOID Xfer_Recycle(MY_XFER_EL** WaitList, MY_XFER_EL** AvailList)
{
MY_XFER_EL* move = *WaitList;
DL_DELETE(*WaitList, move);
if (g_LoopCounter < MAX_XFERS)
DL_APPEND(*AvailList, move);
}
DWORD __cdecl main(int argc, char* argv[])
{
KLST_HANDLE deviceList = NULL;
KLST_DEVINFO_HANDLE deviceInfo = NULL;
KUSB_HANDLE usbHandle = NULL;
int i;
BOOL success;
BM_TEST_TYPE testType = BM_TEST_TYPE_LOOP;
MY_XFER_EL xfersTx[MAX_PENDING_IO];
MY_XFER_EL xfersRx[MAX_PENDING_IO];
MY_XFER_EL* xferAvailListTx = NULL;
MY_XFER_EL* xferAvailListRx = NULL;
MY_XFER_EL* xferWaitListTx = NULL;
MY_XFER_EL* xferWaitListRx = NULL;
memset(xfersTx, 0, sizeof(xfersTx));
memset(xfersRx, 0, sizeof(xfersRx));
for (i = 0; i < MAX_PENDING_IO; i++)
{
DL_APPEND(xferAvailListTx, &xfersTx[i]);
DL_APPEND(xferAvailListRx, &xfersRx[i]);
}
if (!Examples_GetTestDevice(&deviceList, &deviceInfo, argc, argv))
return GetLastError();
LibK_LoadDriverAPI(&Usb, deviceInfo->DriverID);
if (!Usb.Init(&usbHandle, deviceInfo))
{
g_ErrorCode = GetLastError();
printf("Usb.Init failed. ErrorCode: %08Xh\n", g_ErrorCode);
goto Done;
}
printf("Device opened successfully!\n");
OvlK_Init(&gOvlPool, usbHandle, (MAX_PENDING_IO + 1) * 2, 0);
success = Bench_Configure(usbHandle, BM_COMMAND_SET_TEST, 0, NULL, &testType);
if (!success) goto Done;
do
{
while (xferAvailListRx && xferAvailListTx && g_LoopCounter < MAX_XFERS)
{
g_LoopCounter++;
Xfer_Submit(usbHandle, &xferAvailListRx, &xferWaitListRx, EP_RX);
Xfer_Submit(usbHandle, &xferAvailListTx, &xferWaitListTx, EP_TX);
}
if (xferWaitListTx && xferWaitListRx)
{
Xfer_Wait(xferWaitListRx, XFER_TIMEOUT, EP_RX);
Xfer_Wait(xferWaitListTx, XFER_TIMEOUT, EP_TX);
Xfer_Recycle(&xferWaitListTx, &xferAvailListTx);
Xfer_Recycle(&xferWaitListRx, &xferAvailListRx);
}
}
while(xferWaitListTx && xferWaitListRx);
Done:
Usb.Free(usbHandle);
LstK_Free(deviceList);
OvlK_Free(gOvlPool);
return g_ErrorCode;
}