--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/win32/usbrflct/usbrflct.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,995 @@
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\win32\usbrflct\usbrflct.cpp
+// Win32 USB test program USBRFLCT: performs I/O with a device running the
+// Symbian OS test program T_USB, using the generic USB device driver USBIO.
+// === Includes ===
+//
+//
+
+#include <windows.h>
+#include <stdio.h>
+#include <iostream.h>
+#include <time.h>
+
+#include "usbio.h" // USBIO Dev Kit
+#include "usbiopipe.h" // ditto
+
+
+// === Global Defines ===
+
+// The version of this program
+#define VERSION_MAJOR 1
+#ifdef VERSION_MINOR
+# undef VERSION_MINOR // VERSION_MINOR sometimes yields funny compiler warning (c4005)
+#endif
+#define VERSION_MINOR 6
+#ifdef VERSION_MICRO
+# undef VERSION_MICRO // ditto
+#endif
+#define VERSION_MICRO 0
+
+// The version of the USBIO driver this program is compiled against
+#define USBIO_VERSION_MAJOR 2
+#define USBIO_VERSION_MINOR 41
+
+#define MAX_DESCRIPTOR_BUFFER_SIZE 2047
+
+// === Global Vars ===
+
+// Our own private GUID (also used in the .inf file as 'DriverUserInterfaceGuid')
+// {55606403-E62D-4707-9F56-40D48C6736D0}
+static const GUID g_UsbioID =
+ {0x55606403, 0xe62d, 0x4707, {0x9f, 0x56, 0x40, 0xd4, 0x8c, 0x67, 0x36, 0xd0}};
+
+// Handle for USB device list
+static HDEVINFO g_DevList = NULL;
+
+// USBIO supported device
+static CUsbIo g_UsbDev;
+static CUsbIoPipe g_BulkOutPipe;
+static CUsbIoPipe g_BulkInPipe;
+
+// 2 Bulk endpoints
+static UCHAR g_ucBulkOutEndpoint = 0;
+static UCHAR g_ucBulkInEndpoint = 0;
+
+// Read/write buffer
+static const DWORD KBufferSize = 1024 * 1024;
+static const DWORD KPreambleLength = 8;
+static BYTE Data[KBufferSize]; // the read/write buffer
+static DWORD Length; // Length of a transfer
+static time_t T_0; // the starting time
+
+static CUsbIoBuf g_Buf((VOID*) Data, KBufferSize); // the data buffer
+static CUsbIoBuf g_ZlpBuf (NULL, 0); // the data buffer
+
+static DWORD dwRC = USBIO_ERR_SUCCESS; // global error indicator
+
+enum
+ {
+ ELoop,
+ ELoopDebug,
+ EReceiveOnly,
+ ETransmitOnly
+ };
+
+static int TransferMode = ELoop;
+static bool VerboseMode = false;
+static bool ZlpMode = false;
+
+static unsigned int maxOutPacketSize = 0;
+
+// The version of T_USB we require (at least)
+static const DWORD KTusbVersion = 20070524;
+
+// After how many iterations to update the CRT:
+static const int KLoopModeDisplayUpdate = 1024;
+// After how many iterations (= MBytes) to update the CRT:
+static const int KUniModeDisplayUpdate = 10;
+
+// Helper #defines
+
+#define PRINT_IF_VERBOSE(string) \
+ do { \
+ if (VerboseMode) \
+ { \
+ printf(string); \
+ } \
+ } while (0)
+
+#define PRINT_IF_VERBOSE1(string, a) \
+ do { \
+ if (VerboseMode) \
+ { \
+ printf(string, a); \
+ } \
+ } while (0)
+
+
+// === Functions ===
+
+//
+// Process the command line arguments, printing a helpful message
+// if none are supplied.
+//
+static int ProcessCmdLine(int argc, char* argv[])
+ {
+ char help_text[] =
+ "* Syntax: usbrflct [options]\n"
+ "* Options:\n"
+ "* /[r|t] receive|transmit only; default is to loop\n"
+ "* /z zero length packet at end of a transmission\n"
+ "* (only if last packet is full length)\n"
+ "* /l loop mode with stats printed for every iteration\n"
+ "* /v verbose driver & program output\n"
+ "* /[h|?] displays this help text\n"
+ "\n";
+
+ for (int i = 1; i < argc; i++)
+ {
+ strupr(argv[i]);
+ if ((argv[i][0] == '-') || (argv[i][0] == '/'))
+ {
+ switch (argv[i][1])
+ {
+ case 'R':
+ case 'r':
+ TransferMode = EReceiveOnly;
+ break;
+ case 'T':
+ case 't':
+ TransferMode = ETransmitOnly;
+ break;
+ case 'L':
+ case 'l':
+ TransferMode = ELoopDebug;
+ break;
+ case 'V':
+ case 'v':
+ VerboseMode = true;
+ break;
+ case 'Z':
+ case 'z':
+ ZlpMode = true;
+ break;
+ case '?':
+ case 'H':
+ case 'h':
+ cout << help_text;
+ return -1;
+ default:
+ cout << "* Invalid argument: " << argv[i] << "\n";
+ cout << help_text;
+ return -1;
+ }
+ }
+ }
+ return 0;
+ }
+
+
+static void OpenUsbDevice()
+ {
+ CUsbIo::DestroyDeviceList(g_DevList);
+
+ // Enumerate attached USB devices supported by USBIO
+ g_DevList = CUsbIo::CreateDeviceList(&g_UsbioID);
+
+ // Open first device in list
+ dwRC = g_UsbDev.Open(0, g_DevList, &g_UsbioID);
+
+ PRINT_IF_VERBOSE1("\nCUsbIo::Open returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_VERSION_MISMATCH)
+ {
+ printf("\n* Error: \"The API version reported by the USBRFLCT driver\n" \
+ "* does not match the expected version.\"\n");
+ printf("* The driver will need to be updated as follows:\n");
+ printf("* 1. Connect the device to the PC & start T_USB,\n" \
+ "* then find the USB device in the Windows Device Manager\n" \
+ "* ('Control Panel'->'System'->'Hardware'->'Device Manager').\n" \
+ "* Right click on the device name and choose 'Uninstall...'.\n");
+ printf("* 2. In c:\\winnt\\inf\\, find (by searching for \"Symbian\") and\n" \
+ "* delete the *.INF file that was used to install the existing\n" \
+ "* version of USBRFLCT.SYS. Make sure to also delete the\n" \
+ "* precompiled version of that file (<samename>.PNF).\n");
+ printf("* 3. In c:\\winnt\\system32\\drivers\\, delete the file USBRFLCT.SYS.\n");
+ printf("* Then unplug & reconnect the USB device and, when prompted, install\n" \
+ "* the new USBRFLCT.SYS driver using the .INF file from this distribution.\n" \
+ "* (All files can be found under e32test\\win32\\usbrflct_distribution\\.)\n");
+ }
+ }
+
+
+static void CloseUsbDevice()
+ {
+ // Close the device
+ g_UsbDev.Close();
+ PRINT_IF_VERBOSE("CUsbIo::Close called\n");
+ }
+
+
+static void GetDeviceDescriptor()
+ {
+ USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+
+ memset(&DeviceDescriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
+
+ // Get device descriptor
+ dwRC = g_UsbDev.GetDeviceDescriptor(&DeviceDescriptor);
+ PRINT_IF_VERBOSE1("CUsbIo::GetDeviceDescriptor returned <0x%X>\n", dwRC);
+
+ if (VerboseMode && (dwRC == USBIO_ERR_SUCCESS))
+ {
+ printf("\nDEVICE DESCRIPTOR:\n"
+ "bLength = <%u>\n"
+ "bDescriptorType = <%u>\n"
+ "bcdUSB = <%u>\n"
+ "bDeviceClass = <%u>\n"
+ "bDeviceSubClass = <%u>\n"
+ "bDeviceProtocol = <%u>\n"
+ "bMaxPacketSize0 = <%u>\n"
+ "idVendor = <%u>\n"
+ "idProduct = <%u>\n"
+ "bcdDevice = <%u>\n"
+ "iManufacturer = <%u>\n"
+ "iProduct = <%u>\n"
+ "iSerialNumber = <%u>\n"
+ "bNumConfigurations = <%u>\n\n",
+ DeviceDescriptor.bLength,
+ DeviceDescriptor.bDescriptorType,
+ DeviceDescriptor.bcdUSB,
+ DeviceDescriptor.bDeviceClass,
+ DeviceDescriptor.bDeviceSubClass,
+ DeviceDescriptor.bDeviceProtocol,
+ DeviceDescriptor.bMaxPacketSize0,
+ DeviceDescriptor.idVendor,
+ DeviceDescriptor.idProduct,
+ DeviceDescriptor.bcdDevice,
+ DeviceDescriptor.iManufacturer,
+ DeviceDescriptor.iProduct,
+ DeviceDescriptor.iSerialNumber,
+ DeviceDescriptor.bNumConfigurations);
+ }
+ }
+
+
+static void GetConfigurationDescriptor()
+ {
+ CHAR szBuffer[MAX_DESCRIPTOR_BUFFER_SIZE] = "";
+ USB_CONFIGURATION_DESCRIPTOR* pConfigDescriptor = NULL;
+ USB_INTERFACE_DESCRIPTOR* pInterfaceDescriptor = NULL;
+ USB_ENDPOINT_DESCRIPTOR* pEndpointDescriptor = NULL;
+
+ DWORD dwByteCount = MAX_DESCRIPTOR_BUFFER_SIZE;
+
+ memset(szBuffer, 0, sizeof(szBuffer));
+
+ // Get first configuration descriptor
+ dwRC =
+ g_UsbDev.GetConfigurationDescriptor((USB_CONFIGURATION_DESCRIPTOR*) szBuffer,
+ dwByteCount, 0);
+ PRINT_IF_VERBOSE1("CUsbIo::GetConfigurationDescriptor returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ USB_COMMON_DESCRIPTOR* Desc;
+ ULONG rl = dwByteCount;
+ ULONG ulDescLength = 0;
+ CHAR* data = szBuffer;
+
+ while (rl > 0)
+ {
+ Desc = (USB_COMMON_DESCRIPTOR*) data;
+ ulDescLength = Desc->bLength;
+ if ((ulDescLength > rl) || (ulDescLength == 0))
+ {
+ printf("Length remaining too short!\n");
+ rl = 0;
+ }
+ else
+ {
+ switch (Desc->bDescriptorType)
+ {
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ pConfigDescriptor =
+ (USB_CONFIGURATION_DESCRIPTOR*) data;
+ if (VerboseMode)
+ {
+ printf("\nCONFIGURATION DESCRIPTOR:\n"
+ "bLength = <%u>\n"
+ "bDescriptorType = <%u>\n"
+ "wTotalLength = <%u>\n"
+ "bNumInterfaces = <%u>\n"
+ "bConfigurationValue = <%u>\n"
+ "iConfiguration = <%u>\n"
+ "bmAttributes = <%u>\n"
+ "MaxPower = <%u>\n",
+ pConfigDescriptor->bLength,
+ pConfigDescriptor->bDescriptorType,
+ pConfigDescriptor->wTotalLength,
+ pConfigDescriptor->bNumInterfaces,
+ pConfigDescriptor->bConfigurationValue,
+ pConfigDescriptor->iConfiguration,
+ pConfigDescriptor->bmAttributes,
+ pConfigDescriptor->MaxPower);
+ }
+ break;
+ case USB_INTERFACE_DESCRIPTOR_TYPE:
+ pInterfaceDescriptor =
+ (USB_INTERFACE_DESCRIPTOR*) data;
+ if (VerboseMode)
+ {
+ printf("\nINTERFACE DESCRIPTOR: \n"
+ "bLength = <%u>\n"
+ "bDescriptorType = <%u>\n"
+ "bInterfaceNumber = <%u>\n"
+ "bAlternateSetting = <%u>\n"
+ "bNumEndpoints = <%u>\n"
+ "bInterfaceClass = <%u>\n"
+ "bInterfaceSubClass = <%u>\n"
+ "bInterfaceProtocol = <%u>\n"
+ "iInterface = <%u>\n",
+ pInterfaceDescriptor->bLength,
+ pInterfaceDescriptor->bDescriptorType,
+ pInterfaceDescriptor->bInterfaceNumber,
+ pInterfaceDescriptor->bAlternateSetting,
+ pInterfaceDescriptor->bNumEndpoints,
+ pInterfaceDescriptor->bInterfaceClass,
+ pInterfaceDescriptor->bInterfaceSubClass,
+ pInterfaceDescriptor->bInterfaceProtocol,
+ pInterfaceDescriptor->iInterface);
+ }
+ break;
+ case USB_ENDPOINT_DESCRIPTOR_TYPE:
+ pEndpointDescriptor =
+ (USB_ENDPOINT_DESCRIPTOR*) data;
+ if (VerboseMode)
+ {
+ printf("\nENDPOINT DESCRIPTOR: \n"
+ "bLength = <%u>\n"
+ "bDescriptorType = <%u>\n"
+ "bEndpointAddress = <%u>\n"
+ "bmAttributes = <%u>\n"
+ "wMaxPacketSize = <%u>\n"
+ "bInterval = <%u>\n",
+ pEndpointDescriptor->bLength,
+ pEndpointDescriptor->bDescriptorType,
+ pEndpointDescriptor->bEndpointAddress,
+ pEndpointDescriptor->bmAttributes,
+ pEndpointDescriptor->wMaxPacketSize,
+ pEndpointDescriptor->bInterval);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ data += ulDescLength;
+ rl -= ulDescLength;
+ }
+ }
+ PRINT_IF_VERBOSE("\n");
+ }
+
+
+static void GetStringDescriptor()
+ {
+ CHAR szBuffer[MAX_DESCRIPTOR_BUFFER_SIZE] = "";
+ USB_STRING_DESCRIPTOR* pStringDescriptor = NULL;
+ DWORD dwByteCount = MAX_DESCRIPTOR_BUFFER_SIZE;
+
+ memset(szBuffer, 0, sizeof(szBuffer));
+
+ // Get string descriptor
+ dwRC = g_UsbDev.GetStringDescriptor((USB_STRING_DESCRIPTOR*) szBuffer,
+ dwByteCount, 1, 0);
+ PRINT_IF_VERBOSE1("CUsbIo::GetStringDescriptor returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ pStringDescriptor = (USB_STRING_DESCRIPTOR*) szBuffer;
+ if (VerboseMode)
+ {
+ printf("\nSTRING DESCRIPTOR:\n"
+ "bLength = <%u>\n"
+ "bDescriptorType = <%u>\n"
+ "bString = <", // output continues below!
+ pStringDescriptor->bLength,
+ pStringDescriptor->bDescriptorType);
+ }
+ INT i = 0;
+ CHAR* Ptr = szBuffer;
+ for (i = 2, Ptr += 2;
+ i < pStringDescriptor->bLength;
+ i += 2, Ptr += 2)
+ {
+ PRINT_IF_VERBOSE1("%c", *Ptr);
+ }
+ PRINT_IF_VERBOSE(">\n\n");
+ }
+ }
+
+
+static void SetConfiguration()
+ {
+ USBIO_SET_CONFIGURATION SetConfig;
+
+ memset(&SetConfig, 0, sizeof(USBIO_SET_CONFIGURATION));
+
+ // Set the first configuration as active
+ SetConfig.ConfigurationIndex = 0;
+ SetConfig.NbOfInterfaces = 1;
+ SetConfig.InterfaceList[0].InterfaceIndex = 0;
+ SetConfig.InterfaceList[0].AlternateSettingIndex = 0;
+ SetConfig.InterfaceList[0].MaximumTransferSize = KBufferSize;
+ dwRC = g_UsbDev.SetConfiguration(&SetConfig);
+ PRINT_IF_VERBOSE1("CUsbIo::SetConfiguration returned <0x%X>\n", dwRC);
+ }
+
+
+static void GetConfigurationInfo()
+ {
+ USBIO_CONFIGURATION_INFO ConfigInfo;
+ USHORT i = 0;
+
+ memset(&ConfigInfo, 0, sizeof(USBIO_CONFIGURATION_INFO));
+
+ dwRC = g_UsbDev.GetConfigurationInfo(&ConfigInfo);
+ PRINT_IF_VERBOSE1("CUsbIo::GetConfigurationInfo returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ if (VerboseMode)
+ {
+ printf("\nCONFIGURATION INFO:\n"
+ "NbOfInterfaces = <%lu>\n"
+ "NbOfPipes = <%lu>\n",
+ ConfigInfo.NbOfInterfaces,
+ ConfigInfo.NbOfPipes);
+ }
+ for (i = 0; i < ConfigInfo.NbOfInterfaces; i++)
+ {
+ if (VerboseMode)
+ {
+ printf("\nINTERFACE <%u>:\n", i + 1);
+ printf("InterfaceNumber = <%u>\n"
+ "AlternateSetting = <%u>\n"
+ "Class = <%u>\n"
+ "SubClass = <%u>\n"
+ "Protocol = <%u>\n"
+ "NumberOfPipes = <%u>\n"
+ "reserved1 = <%u>\n"
+ "reserved2 = <%u>\n",
+ ConfigInfo.InterfaceInfo[i].InterfaceNumber,
+ ConfigInfo.InterfaceInfo[i].AlternateSetting,
+ ConfigInfo.InterfaceInfo[i].Class,
+ ConfigInfo.InterfaceInfo[i].SubClass,
+ ConfigInfo.InterfaceInfo[i].Protocol,
+ ConfigInfo.InterfaceInfo[i].NumberOfPipes,
+ ConfigInfo.InterfaceInfo[i].reserved1,
+ ConfigInfo.InterfaceInfo[i].reserved2);
+ }
+ }
+ for (i = 0; i < ConfigInfo.NbOfPipes; i++)
+ {
+ PRINT_IF_VERBOSE("\n");
+ if ((ConfigInfo.PipeInfo[i].PipeType == PipeTypeBulk) &&
+ !(ConfigInfo.PipeInfo[i].EndpointAddress & 0x80))
+ {
+ PRINT_IF_VERBOSE("Bulk OUT pipe found:\n");
+ g_ucBulkOutEndpoint = ConfigInfo.PipeInfo[i].EndpointAddress;
+ maxOutPacketSize = ConfigInfo.PipeInfo[i].MaximumPacketSize;
+ }
+ else if ((ConfigInfo.PipeInfo[i].PipeType == PipeTypeBulk) &&
+ (ConfigInfo.PipeInfo[i].EndpointAddress & 0x80))
+ {
+ PRINT_IF_VERBOSE("Bulk IN pipe found:\n");
+ g_ucBulkInEndpoint = ConfigInfo.PipeInfo[i].EndpointAddress;
+ }
+ if (VerboseMode)
+ {
+ printf("PIPE <%u>\n", i + 1);
+ printf("PipeType = <%d>\n"
+ "MaximumTransferSize = <%lu>\n"
+ "MaximumPacketSize = <%u>\n"
+ "EndpointAddress = <%u>\n"
+ "Interval = <%u>\n"
+ "InterfaceNumber = <%u>\n"
+ "reserved1 = <%u>\n"
+ "reserved2 = <%u>\n"
+ "reserved3 = <%u>\n",
+ ConfigInfo.PipeInfo[i].PipeType,
+ ConfigInfo.PipeInfo[i].MaximumTransferSize,
+ ConfigInfo.PipeInfo[i].MaximumPacketSize,
+ ConfigInfo.PipeInfo[i].EndpointAddress,
+ ConfigInfo.PipeInfo[i].Interval,
+ ConfigInfo.PipeInfo[i].InterfaceNumber,
+ ConfigInfo.PipeInfo[i].reserved1,
+ ConfigInfo.PipeInfo[i].reserved2,
+ ConfigInfo.PipeInfo[i].reserved3);
+ }
+ }
+ }
+ PRINT_IF_VERBOSE("\n");
+ }
+
+
+static void OpenPipes()
+ {
+ CUsbIo::DestroyDeviceList(g_DevList);
+
+ // Enumerate attached USB devices supported by USBIO
+ g_DevList = CUsbIo::CreateDeviceList(&g_UsbioID);
+
+ // Create the bulk OUT pipe
+ dwRC = g_BulkOutPipe.Bind(0, g_ucBulkOutEndpoint, g_DevList, &g_UsbioID);
+ PRINT_IF_VERBOSE1("CUsbIoPipe::Bind (Bulk OUT) returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // Create the bulk IN pipe
+ dwRC = g_BulkInPipe.Bind(0, g_ucBulkInEndpoint, g_DevList, &g_UsbioID);
+ PRINT_IF_VERBOSE1("CUsbIoPipe::Bind (Bulk IN) returned <0x%X>\n", dwRC);
+ }
+ PRINT_IF_VERBOSE("\n");
+ }
+
+
+static void ClosePipes()
+ {
+ // Close down the bulk OUT pipe
+ dwRC = g_BulkOutPipe.Unbind();
+ PRINT_IF_VERBOSE1("CUsbIoPipe::Unbind (Bulk OUT) returned <0x%X>\n", dwRC);
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // Close down the bulk IN pipe
+ dwRC = g_BulkInPipe.Unbind();
+ PRINT_IF_VERBOSE1("CUsbIoPipe::Unbind (Bulk IN) returned <0x%X>\n", dwRC);
+ }
+ }
+
+
+static void ReceiveVersion()
+ {
+ // Here we (hope to) read an 8 byte packet containing the T_USB version.
+ printf("* Waiting for T_USB version packet to arrive...");
+
+ // The first 4 bytes are interpreted as an int32 value.
+ DWORD bytes_read = 0;
+ g_Buf.NumberOfBytesToTransfer = KPreambleLength;
+ g_BulkInPipe.Read(&g_Buf);
+ dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
+ printf(" done.\n");
+ bytes_read = g_Buf.BytesTransferred;
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ if (bytes_read < KPreambleLength)
+ {
+ printf("* Read less bytes (%d) than expected (%d).\n",
+ bytes_read, KPreambleLength);
+ dwRC = USBIO_ERR_FAILED;
+ return;
+ }
+ }
+ else
+ {
+ printf("\n* Error: CUsbIoPipe::Read (version) returned <0x%X>\n", dwRC);
+ return;
+ }
+ // First make sure it's actually the version packet, and not
+ // a data preamble packet of an old T_USB.
+ if (!(Data[4] == 'V' &&
+ Data[5] == 'e' &&
+ Data[6] == 'r' &&
+ Data[7] == 's'))
+ {
+ printf("* Inadequate version of T_USB: no version packet was sent (we need at least %d)\n",
+ KTusbVersion);
+ dwRC = USBIO_ERR_FAILED;
+ return;
+ }
+ DWORD tusb_version = *((ULONG*) Data); // first 4 bytes
+ if (tusb_version < KTusbVersion)
+ {
+ printf("* Inadequate version of T_USB: %d (we need at least %d)\n",
+ tusb_version, KTusbVersion);
+ dwRC = USBIO_ERR_FAILED;
+ return;
+ }
+ printf("* Suitable version of T_USB found: %d.\n", tusb_version);
+ }
+
+
+static void SendVersion()
+ {
+ // Here we send an 8 byte packet containing USBRFLCT's + USBIO's versions.
+ printf("* Sending our version packet to T_USB...");
+
+ DWORD bytes_written = 0;
+ g_Buf.NumberOfBytesToTransfer = KPreambleLength;
+ Data[0] = VERSION_MAJOR;
+ Data[1] = VERSION_MINOR;
+ Data[2] = VERSION_MICRO;
+ Data[3] = USBIO_VERSION_MAJOR;
+ Data[4] = USBIO_VERSION_MINOR;
+ g_BulkOutPipe.Write(&g_Buf);
+ dwRC = g_BulkOutPipe.WaitForCompletion(&g_Buf, INFINITE);
+ printf(" done.\n");
+ bytes_written = g_Buf.BytesTransferred;
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ if (bytes_written < KPreambleLength)
+ {
+ printf("* Wrote less bytes (%d) than requested (%d).\n",
+ bytes_written, KPreambleLength);
+ dwRC = USBIO_ERR_FAILED;
+ }
+ }
+ else
+ {
+ printf("\n* Error: CUsbIoPipe::Write (version) returned <0x%X>\n", dwRC);
+ }
+ }
+
+
+static void ExchangeVersions()
+ {
+ SendVersion();
+ if (dwRC != USBIO_ERR_SUCCESS)
+ return;
+ ReceiveVersion();
+ }
+
+
+static void GetLength()
+ {
+ // The first two bytes are interpreted as a length value.
+ DWORD bytes_read = KPreambleLength;
+ g_Buf.NumberOfBytesToTransfer = KPreambleLength;
+
+ g_BulkInPipe.Read(&g_Buf);
+ dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
+ bytes_read = g_Buf.BytesTransferred;
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ if (bytes_read < KPreambleLength)
+ {
+ printf("* Read less bytes (%d) than expected (%d).\n",
+ bytes_read, KPreambleLength);
+ dwRC = USBIO_ERR_FAILED;
+ return;
+ }
+ }
+ else
+ {
+ printf("\n* Error: CUsbIoPipe::Read (length) returned <0x%X>\n", dwRC);
+ return;
+ }
+ Length = *((ULONG*) Data); // first 4 bytes
+ if (Length > KBufferSize)
+ {
+ printf("* This is too much: %d (our buffer is too small: %d)\n",
+ Length, KBufferSize);
+ dwRC = USBIO_ERR_FAILED;
+ }
+ if (VerboseMode)
+ {
+ printf("* Just read %d bytes, now assuming transfer length is %d bytes.\n",
+ bytes_read, Length);
+ }
+ else if (TransferMode == EReceiveOnly || TransferMode == ETransmitOnly)
+ {
+ printf("* Single transfer size: %d bytes.\n", Length);
+ }
+ }
+
+
+static void ReadData()
+ {
+ // We have to setup a read for at least one byte in order to get
+ // the host to issue IN tokens for our zero-byte read:
+ if (Length == 0)
+ g_Buf.NumberOfBytesToTransfer = 1;
+ else
+ g_Buf.NumberOfBytesToTransfer = Length;
+
+ g_BulkInPipe.Read(&g_Buf);
+ dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
+ DWORD bytes_read = g_Buf.BytesTransferred;
+
+ if (dwRC != USBIO_ERR_SUCCESS)
+ {
+ printf("\n* Error: CUsbIoPipe::Read (data) returned <0x%X>\n", dwRC);
+ }
+ else
+ {
+ if (bytes_read != Length)
+ {
+ printf("* Read more/less bytes (%d) than expected (%d).\n",
+ bytes_read, Length);
+ dwRC = USBIO_ERR_FAILED;
+ }
+ else
+ {
+ PRINT_IF_VERBOSE1("* Read %d bytes.\n", Length);
+ }
+ }
+ }
+
+
+static void WriteData()
+ {
+ DWORD bytes_written = Length;
+
+ g_Buf.NumberOfBytesToTransfer = bytes_written;
+
+ g_BulkOutPipe.Write(&g_Buf);
+ dwRC = g_BulkOutPipe.WaitForCompletion(&g_Buf, INFINITE);
+ if (ZlpMode && (Length >= maxOutPacketSize) && ((Length % maxOutPacketSize) == 0))
+ {
+ // writes a zero length packet
+ g_BulkOutPipe.Write(&g_ZlpBuf);
+ dwRC = g_BulkOutPipe.WaitForCompletion(&g_ZlpBuf, INFINITE);
+ }
+
+
+ bytes_written = g_Buf.BytesTransferred;
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ PRINT_IF_VERBOSE1("* Wrote %d bytes.\n", bytes_written);
+ }
+ else
+ {
+ printf("\n* Error: CUsbIoPipe::Write returned <0x%X>\n", dwRC);
+ }
+ }
+
+
+void PrintStats()
+ {
+ static DWORD loop = 0; // the loop counter
+ static double xfer_size = 0; // the total transfer amount so far
+ time_t t_1 = time(NULL); // current time
+ double t_diff = difftime(t_1, T_0); // this yields current seconds since start
+ xfer_size += (KPreambleLength + (2 * Length)) * KLoopModeDisplayUpdate; //
+ double xfer_rate = xfer_size / t_diff; // mean transfer rate since start
+ loop += KLoopModeDisplayUpdate;
+ printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s \r",
+ loop, Length, xfer_size, xfer_rate);
+ }
+
+
+void PrintStatsEveryLoop()
+ {
+ static DWORD loop = 0; // the loop counter
+ static double xfer_size = 0; // the total transfer amount so far
+ time_t t_1 = time(NULL); // current time
+ double t_diff = difftime(t_1, T_0); // this yields current seconds since start
+ xfer_size += (KPreambleLength + (2 * Length)); //
+ double xfer_rate = xfer_size / t_diff; // mean transfer rate since start
+ printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s \r",
+ ++loop, Length, xfer_size, xfer_rate);
+ }
+
+
+void PrintUnidirStats()
+ {
+ static DWORD loop = 0; // the loop counter
+ static double xfer_size = 0; // the total transfer amount so far
+ time_t t_1 = time(NULL); // current time
+ double t_diff = difftime(t_1, T_0); // this yields current seconds since start
+ xfer_size += Length * KUniModeDisplayUpdate;
+ double xfer_rate = xfer_size / t_diff; // mean transfer rate since start
+ loop += KUniModeDisplayUpdate;
+ printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s \r",
+ loop, Length, xfer_size, xfer_rate);
+ }
+
+
+static void LoopTransfer()
+ {
+ printf("* Loop Transfers -- reading & writing alternately.\n");
+
+ T_0 = time(NULL); // starting time
+
+ while (dwRC == USBIO_ERR_SUCCESS)
+ {
+ static DWORD n = 0;
+
+ // First we get the length (+ the packet size)
+ GetLength();
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // Then we read 'Length' bytes
+ ReadData();
+ }
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // Now we send the received data back to the client.
+ WriteData();
+ }
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // Finally, sometimes we print some statistics
+ if (TransferMode == ELoopDebug)
+ PrintStatsEveryLoop();
+ else if ((++n % KLoopModeDisplayUpdate) == 0)
+ PrintStats();
+ }
+ }
+ }
+
+
+static void ReceiveOnlyTransfer()
+ {
+ printf("* Receive-only transfers (IN).\n");
+
+ // First (and only once) we get the transfer length (+ the packet size)
+ GetLength();
+
+ T_0 = time(NULL); // starting time
+
+ while (dwRC == USBIO_ERR_SUCCESS)
+ {
+ static DWORD n = -1;
+ static DWORD pktNum;
+
+ // Then we read 'Length' bytes
+ ReadData();
+ pktNum = *(DWORD *)&Data;
+ if (pktNum != ++n)
+ {
+ printf ("\n* Error: rcv'd wrong pkt number: 0x%x (expected: 0x%x)\n", pktNum, n);
+ // reset from the received packet number, so that ...
+ // if a packet is lost or duplicated a single error is reported
+ n = pktNum;
+ }
+ // Finally, sometimes we print some statistics
+ if ((n % KUniModeDisplayUpdate) == 0)
+ PrintUnidirStats();
+ }
+ }
+
+
+static void TransmitOnlyTransfer()
+ {
+ printf("* Transmit-only transfers (OUT).\n");
+
+ // First (and only once) we get the transfer length (+ the packet size)
+ GetLength();
+
+ T_0 = time(NULL); // starting time
+
+ while (dwRC == USBIO_ERR_SUCCESS)
+ {
+ static DWORD n = 0;
+ // First the packet number is put into the first four bytes
+ *(DWORD *)&Data = n++;
+ // Then we write 'Length' bytes
+ WriteData();
+
+ // Finally, sometimes we print some statistics
+ if ((n % KUniModeDisplayUpdate) == 0)
+ PrintUnidirStats();
+ }
+ }
+
+
+static void DoTransfers()
+ {
+ switch (TransferMode)
+ {
+ case ELoop:
+ case ELoopDebug:
+ LoopTransfer();
+ break;
+ case EReceiveOnly:
+ ReceiveOnlyTransfer();
+ break;
+ case ETransmitOnly:
+ TransmitOnlyTransfer();
+ break;
+ default:
+ dwRC = -1;
+ break;
+ }
+ }
+
+
+static void Delay(int milliseconds)
+ {
+ printf("* Short wait... ");
+ Sleep(milliseconds);
+ printf("done.\n");
+ }
+
+
+static void PrintHello()
+ {
+ printf("*--------------------------------------------------\n");
+ printf("* USBRFLCT v%d.%d.%d (for use with USBRFLCT.SYS v%d.%d)\n",
+ VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO,
+ USBIO_VERSION_MAJOR, USBIO_VERSION_MINOR);
+ printf("* USB Reflector Test Program / T_USB Host-side Part\n");
+ printf("* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).\n");
+ printf("*--------------------------------------------------\n");
+ }
+
+
+int main(int argc, char* argv[])
+ {
+ PrintHello();
+
+ if (ProcessCmdLine(argc, argv) != 0)
+ return -1;
+
+ OpenUsbDevice();
+
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ GetDeviceDescriptor();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ GetConfigurationDescriptor();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ GetStringDescriptor();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ SetConfiguration();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ // In order to give the USB device-side program (t_usb)
+ // enough time after getting configured to carry out
+ // some device tests, we wait here for a short while
+ // before proceeding:
+ Delay(2000);
+ GetConfigurationInfo();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ OpenPipes();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ ExchangeVersions();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ DoTransfers();
+ }
+ if (dwRC == USBIO_ERR_SUCCESS)
+ {
+ ClosePipes();
+ }
+
+ CloseUsbDevice();
+
+ return 0;
+ }
+
+
+// --eof