#include "examples.h"
#define SC_GET_STREAM_DATA 0xb1
#define SC_SET_STREAM_DATA 0xb2
#define EP_TX 0x00
#define EP_RX 0x80
#define EP_PACKET_SIZE 16
#define XFER_LENGTH (EP_PACKET_SIZE)
#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;
KUSB_SETUP_PACKET SetupPacket;
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;
UCHAR chStart;
int pos;
xfer->Length = XFER_LENGTH;
if (CounterTx % XFER_LENGTH)
chStart = CounterTx % XFER_LENGTH;
else
chStart = 0;
for (pos=chStart; pos < XFER_LENGTH+chStart; pos++)
{
xfer->Buffer[pos-chStart]=(UCHAR)(pos + (UCHAR)'A');
}
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))
{
g_ErrorCode = GetLastError();
printf("OvlK_Acquire failed. ErrorCode: %08Xh\n", g_ErrorCode);
return FALSE;
}
move->SetupPacket.BmRequest.Type = BMREQUEST_TYPE_VENDOR;
move->SetupPacket.BmRequest.Recipient = BMREQUEST_RECIPIENT_INTERFACE;
if (USB_ENDPOINT_DIRECTION_IN(PipeID))
{
move->Length = XFER_LENGTH;
move->SetupPacket.BmRequest.Dir = BMREQUEST_DIR_DEVICE_TO_HOST;
move->SetupPacket.Length = (USHORT)move->Length;
move->SetupPacket.Request = SC_GET_STREAM_DATA;
}
else
{
OnDataNeeded(move, PipeID);
move->SetupPacket.BmRequest.Dir = BMREQUEST_DIR_HOST_TO_DEVICE;
move->SetupPacket.Length = (USHORT)move->Length;
move->SetupPacket.Request = SC_SET_STREAM_DATA;
}
Usb.ControlTransfer(usbHandle, *((WINUSB_SETUP_PACKET*)&move->SetupPacket), move->Buffer, move->Length, NULL, move->Ovl);
if ((move->ErrorCode = GetLastError()) != ERROR_IO_PENDING)
{
g_ErrorCode = move->ErrorCode;
printf("Usb.ControlTransfer 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)
{
OvlK_Release(PendingList->Ovl);
return FALSE;
}
if (!OvlK_WaitAndRelease(PendingList->Ovl, Timeout, &PendingList->Length))
{
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;
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");
if (!OvlK_Init(&gOvlPool, usbHandle, MAX_PENDING_IO * 2, 0))
{
g_ErrorCode = GetLastError();
printf("OvlK_Init failed. ErrorCode: %08Xh\n", g_ErrorCode);
goto Done;
}
do
{
while (xferAvailListRx && xferAvailListTx && g_LoopCounter < MAX_XFERS)
{
g_LoopCounter++;
Xfer_Submit(usbHandle, &xferAvailListTx, &xferWaitListTx, EP_TX);
Xfer_Submit(usbHandle, &xferAvailListRx, &xferWaitListRx, EP_RX);
}
if (xferWaitListTx && xferWaitListRx)
{
Xfer_Wait(xferWaitListTx, XFER_TIMEOUT, EP_TX);
Xfer_Wait(xferWaitListRx, XFER_TIMEOUT, EP_RX);
Xfer_Recycle(&xferWaitListTx, &xferAvailListTx);
Xfer_Recycle(&xferWaitListRx, &xferAvailListRx);
}
}
while(xferWaitListTx && xferWaitListRx);
Done:
Usb.Free(usbHandle);
LstK_Free(deviceList);
OvlK_Free(gOvlPool);
return g_ErrorCode;
}