kerneltest/e32test/win32/usbrflct/usbrflct.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\win32\usbrflct\usbrflct.cpp
       
    15 // Win32 USB test program USBRFLCT: performs I/O with a device running the
       
    16 // Symbian OS test program T_USB, using the generic USB device driver USBIO.
       
    17 // === Includes ===
       
    18 // 
       
    19 //
       
    20 
       
    21 #include <windows.h>
       
    22 #include <stdio.h>
       
    23 #include <iostream.h>
       
    24 #include <time.h>
       
    25 
       
    26 #include "usbio.h"											// USBIO Dev Kit
       
    27 #include "usbiopipe.h"										// ditto
       
    28 
       
    29 
       
    30 // === Global Defines ===
       
    31 
       
    32 // The version of this program
       
    33 #define VERSION_MAJOR  1
       
    34 #ifdef VERSION_MINOR
       
    35 # undef VERSION_MINOR						  // VERSION_MINOR sometimes yields funny compiler warning (c4005)
       
    36 #endif
       
    37 #define VERSION_MINOR  6
       
    38 #ifdef VERSION_MICRO
       
    39 # undef VERSION_MICRO						  // ditto
       
    40 #endif
       
    41 #define VERSION_MICRO  0
       
    42 
       
    43 // The version of the USBIO driver this program is compiled against
       
    44 #define USBIO_VERSION_MAJOR  2
       
    45 #define USBIO_VERSION_MINOR  41
       
    46 
       
    47 #define MAX_DESCRIPTOR_BUFFER_SIZE 2047
       
    48 
       
    49 // === Global Vars ===
       
    50 
       
    51 // Our own private GUID (also used in the .inf file as 'DriverUserInterfaceGuid')
       
    52 // {55606403-E62D-4707-9F56-40D48C6736D0}
       
    53 static const GUID g_UsbioID =
       
    54 	{0x55606403, 0xe62d, 0x4707, {0x9f, 0x56, 0x40, 0xd4, 0x8c, 0x67, 0x36, 0xd0}};
       
    55 
       
    56 // Handle for USB device list
       
    57 static HDEVINFO g_DevList = NULL;
       
    58 
       
    59 // USBIO supported device
       
    60 static CUsbIo g_UsbDev;
       
    61 static CUsbIoPipe g_BulkOutPipe;
       
    62 static CUsbIoPipe g_BulkInPipe;
       
    63 
       
    64 // 2 Bulk endpoints
       
    65 static UCHAR g_ucBulkOutEndpoint = 0;
       
    66 static UCHAR g_ucBulkInEndpoint = 0;
       
    67 
       
    68 // Read/write buffer
       
    69 static const DWORD KBufferSize = 1024 * 1024;
       
    70 static const DWORD KPreambleLength = 8;
       
    71 static BYTE Data[KBufferSize];								// the read/write buffer
       
    72 static DWORD Length;										// Length of a transfer
       
    73 static time_t T_0;											// the starting time
       
    74 
       
    75 static CUsbIoBuf g_Buf((VOID*) Data, KBufferSize);		// the data buffer
       
    76 static CUsbIoBuf g_ZlpBuf (NULL, 0);					// the data buffer
       
    77 
       
    78 static DWORD dwRC = USBIO_ERR_SUCCESS;						// global error indicator
       
    79 
       
    80 enum
       
    81 	{
       
    82 	ELoop,
       
    83 	ELoopDebug,
       
    84 	EReceiveOnly,
       
    85 	ETransmitOnly
       
    86 	};
       
    87 
       
    88 static int TransferMode = ELoop;
       
    89 static bool VerboseMode = false;
       
    90 static bool ZlpMode = false;
       
    91 
       
    92 static unsigned int maxOutPacketSize = 0;
       
    93 
       
    94 // The version of T_USB we require (at least)
       
    95 static const DWORD KTusbVersion = 20070524;
       
    96 
       
    97 // After how many iterations to update the CRT:
       
    98 static const int KLoopModeDisplayUpdate = 1024;
       
    99 // After how many iterations (= MBytes) to update the CRT:
       
   100 static const int KUniModeDisplayUpdate = 10;
       
   101 
       
   102 // Helper #defines
       
   103 
       
   104 #define PRINT_IF_VERBOSE(string) \
       
   105 		do { \
       
   106 		if (VerboseMode) \
       
   107 			{ \
       
   108 			printf(string); \
       
   109 			} \
       
   110 		} while (0)
       
   111 
       
   112 #define PRINT_IF_VERBOSE1(string, a) \
       
   113 		do { \
       
   114 		if (VerboseMode) \
       
   115 			{ \
       
   116 			printf(string, a); \
       
   117 			} \
       
   118 		} while (0)
       
   119 
       
   120 
       
   121 // === Functions ===
       
   122 
       
   123 //
       
   124 // Process the command line arguments, printing a helpful message
       
   125 // if none are supplied.
       
   126 //
       
   127 static int ProcessCmdLine(int argc, char* argv[])
       
   128 	{
       
   129 	char help_text[] =
       
   130 		"* Syntax: usbrflct [options]\n"
       
   131 		"* Options:\n"
       
   132 		"* /[r|t]    receive|transmit only; default is to loop\n"
       
   133 		"* /z        zero length packet at end of a transmission\n"
       
   134 		"*	    (only if last packet is full length)\n"
       
   135 		"* /l        loop mode with stats printed for every iteration\n"
       
   136 		"* /v        verbose driver & program output\n"
       
   137 		"* /[h|?]    displays this help text\n"
       
   138 		"\n";
       
   139 
       
   140 	for (int i = 1; i < argc; i++)
       
   141 		{
       
   142 		strupr(argv[i]);
       
   143 		if ((argv[i][0] == '-') || (argv[i][0] == '/'))
       
   144 			{
       
   145 			switch (argv[i][1])
       
   146 				{
       
   147 			case 'R':
       
   148 			case 'r':
       
   149 				TransferMode = EReceiveOnly;
       
   150 				break;
       
   151 			case 'T':
       
   152 			case 't':
       
   153 				TransferMode = ETransmitOnly;
       
   154 				break;
       
   155 			case 'L':
       
   156 			case 'l':
       
   157 				TransferMode = ELoopDebug;
       
   158 				break;
       
   159 			case 'V':
       
   160 			case 'v':
       
   161 				VerboseMode = true;
       
   162 				break;
       
   163 			case 'Z':
       
   164 			case 'z':
       
   165 				ZlpMode = true;
       
   166 				break;
       
   167 			case '?':
       
   168 			case 'H':
       
   169 			case 'h':
       
   170 				cout << help_text;
       
   171 				return -1;
       
   172 			default:
       
   173 				cout << "* Invalid argument: " << argv[i] << "\n";
       
   174 				cout << help_text;
       
   175 				return -1;
       
   176 				}
       
   177 			}
       
   178 		}
       
   179 	return 0;
       
   180 	}
       
   181 
       
   182 
       
   183 static void OpenUsbDevice()
       
   184 	{
       
   185 	CUsbIo::DestroyDeviceList(g_DevList);
       
   186 
       
   187 	// Enumerate attached USB devices supported by USBIO
       
   188 	g_DevList = CUsbIo::CreateDeviceList(&g_UsbioID);
       
   189 
       
   190 	// Open first device in list
       
   191 	dwRC = g_UsbDev.Open(0, g_DevList, &g_UsbioID);
       
   192 
       
   193 	PRINT_IF_VERBOSE1("\nCUsbIo::Open returned <0x%X>\n", dwRC);
       
   194 
       
   195 	if (dwRC == USBIO_ERR_VERSION_MISMATCH)
       
   196 		{
       
   197 		printf("\n* Error: \"The API version reported by the USBRFLCT driver\n" \
       
   198 			   "*         does not match the expected version.\"\n");
       
   199 		printf("* The driver will need to be updated as follows:\n");
       
   200 		printf("* 1. Connect the device to the PC & start T_USB,\n" \
       
   201 			   "* then find the USB device in the Windows Device Manager\n" \
       
   202 			   "* ('Control Panel'->'System'->'Hardware'->'Device Manager').\n" \
       
   203 			   "* Right click on the device name and choose 'Uninstall...'.\n");
       
   204 		printf("* 2. In c:\\winnt\\inf\\, find (by searching for \"Symbian\") and\n" \
       
   205 			   "* delete the *.INF file that was used to install the existing\n" \
       
   206 			   "* version of USBRFLCT.SYS. Make sure to also delete the\n" \
       
   207 			   "* precompiled version of that file (<samename>.PNF).\n");
       
   208 		printf("* 3. In c:\\winnt\\system32\\drivers\\, delete the file USBRFLCT.SYS.\n");
       
   209 		printf("* Then unplug & reconnect the USB device and, when prompted, install\n" \
       
   210 			   "* the new USBRFLCT.SYS driver using the .INF file from this distribution.\n" \
       
   211 			   "* (All files can be found under e32test\\win32\\usbrflct_distribution\\.)\n");
       
   212 		}
       
   213 	}
       
   214 
       
   215 
       
   216 static void CloseUsbDevice()
       
   217 	{
       
   218 	// Close the device
       
   219 	g_UsbDev.Close();
       
   220 	PRINT_IF_VERBOSE("CUsbIo::Close called\n");
       
   221 	}
       
   222 
       
   223 
       
   224 static void GetDeviceDescriptor()
       
   225 	{
       
   226 	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
       
   227 
       
   228 	memset(&DeviceDescriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
       
   229 
       
   230 	// Get device descriptor
       
   231 	dwRC = g_UsbDev.GetDeviceDescriptor(&DeviceDescriptor);
       
   232 	PRINT_IF_VERBOSE1("CUsbIo::GetDeviceDescriptor returned <0x%X>\n", dwRC);
       
   233 
       
   234 	if (VerboseMode && (dwRC == USBIO_ERR_SUCCESS))
       
   235 		{
       
   236 		printf("\nDEVICE DESCRIPTOR:\n"
       
   237 			   "bLength = <%u>\n"
       
   238 			   "bDescriptorType = <%u>\n"
       
   239 			   "bcdUSB = <%u>\n"
       
   240 			   "bDeviceClass = <%u>\n"
       
   241 			   "bDeviceSubClass = <%u>\n"
       
   242 			   "bDeviceProtocol = <%u>\n"
       
   243 			   "bMaxPacketSize0 = <%u>\n"
       
   244 			   "idVendor = <%u>\n"
       
   245 			   "idProduct = <%u>\n"
       
   246 			   "bcdDevice = <%u>\n"
       
   247 			   "iManufacturer = <%u>\n"
       
   248 			   "iProduct = <%u>\n"
       
   249 			   "iSerialNumber = <%u>\n"
       
   250 			   "bNumConfigurations = <%u>\n\n",
       
   251 			   DeviceDescriptor.bLength,
       
   252 			   DeviceDescriptor.bDescriptorType,
       
   253 			   DeviceDescriptor.bcdUSB,
       
   254 			   DeviceDescriptor.bDeviceClass,
       
   255 			   DeviceDescriptor.bDeviceSubClass,
       
   256 			   DeviceDescriptor.bDeviceProtocol,
       
   257 			   DeviceDescriptor.bMaxPacketSize0,
       
   258 			   DeviceDescriptor.idVendor,
       
   259 			   DeviceDescriptor.idProduct,
       
   260 			   DeviceDescriptor.bcdDevice,
       
   261 			   DeviceDescriptor.iManufacturer,
       
   262 			   DeviceDescriptor.iProduct,
       
   263 			   DeviceDescriptor.iSerialNumber,
       
   264 			   DeviceDescriptor.bNumConfigurations);
       
   265 		}
       
   266 	}
       
   267 
       
   268 
       
   269 static void GetConfigurationDescriptor()
       
   270 	{
       
   271 	CHAR szBuffer[MAX_DESCRIPTOR_BUFFER_SIZE] = "";
       
   272 	USB_CONFIGURATION_DESCRIPTOR* pConfigDescriptor = NULL;
       
   273 	USB_INTERFACE_DESCRIPTOR* pInterfaceDescriptor = NULL;
       
   274 	USB_ENDPOINT_DESCRIPTOR* pEndpointDescriptor = NULL;
       
   275 
       
   276 	DWORD dwByteCount = MAX_DESCRIPTOR_BUFFER_SIZE;
       
   277 
       
   278 	memset(szBuffer, 0, sizeof(szBuffer));
       
   279 
       
   280 	// Get first configuration descriptor
       
   281 	dwRC =
       
   282 		g_UsbDev.GetConfigurationDescriptor((USB_CONFIGURATION_DESCRIPTOR*) szBuffer,
       
   283 											dwByteCount, 0);
       
   284 	PRINT_IF_VERBOSE1("CUsbIo::GetConfigurationDescriptor returned <0x%X>\n", dwRC);
       
   285 
       
   286 	if (dwRC == USBIO_ERR_SUCCESS)
       
   287 		{
       
   288 		USB_COMMON_DESCRIPTOR* Desc;
       
   289 		ULONG rl = dwByteCount;
       
   290 		ULONG ulDescLength = 0;
       
   291 		CHAR* data = szBuffer;
       
   292 
       
   293 		while (rl > 0)
       
   294 			{
       
   295 			Desc = (USB_COMMON_DESCRIPTOR*) data;
       
   296 			ulDescLength = Desc->bLength;
       
   297 			if ((ulDescLength > rl) || (ulDescLength == 0))
       
   298 				{
       
   299 				printf("Length remaining too short!\n");
       
   300 				rl = 0;
       
   301 				}
       
   302 			else
       
   303 				{
       
   304 				switch (Desc->bDescriptorType)
       
   305 					{
       
   306 				case USB_CONFIGURATION_DESCRIPTOR_TYPE:
       
   307 					pConfigDescriptor =
       
   308 						(USB_CONFIGURATION_DESCRIPTOR*) data;
       
   309 					if (VerboseMode)
       
   310 						{
       
   311 						printf("\nCONFIGURATION DESCRIPTOR:\n"
       
   312 							   "bLength = <%u>\n"
       
   313 							   "bDescriptorType = <%u>\n"
       
   314 							   "wTotalLength = <%u>\n"
       
   315 							   "bNumInterfaces = <%u>\n"
       
   316 							   "bConfigurationValue = <%u>\n"
       
   317 							   "iConfiguration = <%u>\n"
       
   318 							   "bmAttributes = <%u>\n"
       
   319 							   "MaxPower = <%u>\n",
       
   320 							   pConfigDescriptor->bLength,
       
   321 							   pConfigDescriptor->bDescriptorType,
       
   322 							   pConfigDescriptor->wTotalLength,
       
   323 							   pConfigDescriptor->bNumInterfaces,
       
   324 							   pConfigDescriptor->bConfigurationValue,
       
   325 							   pConfigDescriptor->iConfiguration,
       
   326 							   pConfigDescriptor->bmAttributes,
       
   327 							   pConfigDescriptor->MaxPower);
       
   328 						}
       
   329 					break;
       
   330 				case USB_INTERFACE_DESCRIPTOR_TYPE:
       
   331 					pInterfaceDescriptor =
       
   332 						(USB_INTERFACE_DESCRIPTOR*) data;
       
   333 					if (VerboseMode)
       
   334 						{
       
   335 						printf("\nINTERFACE DESCRIPTOR: \n"
       
   336 							   "bLength = <%u>\n"
       
   337 							   "bDescriptorType = <%u>\n"
       
   338 							   "bInterfaceNumber = <%u>\n"
       
   339 							   "bAlternateSetting = <%u>\n"
       
   340 							   "bNumEndpoints = <%u>\n"
       
   341 							   "bInterfaceClass = <%u>\n"
       
   342 							   "bInterfaceSubClass = <%u>\n"
       
   343 							   "bInterfaceProtocol = <%u>\n"
       
   344 							   "iInterface = <%u>\n",
       
   345 							   pInterfaceDescriptor->bLength,
       
   346 							   pInterfaceDescriptor->bDescriptorType,
       
   347 							   pInterfaceDescriptor->bInterfaceNumber,
       
   348 							   pInterfaceDescriptor->bAlternateSetting,
       
   349 							   pInterfaceDescriptor->bNumEndpoints,
       
   350 							   pInterfaceDescriptor->bInterfaceClass,
       
   351 							   pInterfaceDescriptor->bInterfaceSubClass,
       
   352 							   pInterfaceDescriptor->bInterfaceProtocol,
       
   353 							   pInterfaceDescriptor->iInterface);
       
   354 						}
       
   355 					break;
       
   356 				case USB_ENDPOINT_DESCRIPTOR_TYPE:
       
   357 					pEndpointDescriptor =
       
   358 						(USB_ENDPOINT_DESCRIPTOR*) data;
       
   359 					if (VerboseMode)
       
   360 						{
       
   361 						printf("\nENDPOINT DESCRIPTOR: \n"
       
   362 							   "bLength = <%u>\n"
       
   363 							   "bDescriptorType = <%u>\n"
       
   364 							   "bEndpointAddress = <%u>\n"
       
   365 							   "bmAttributes = <%u>\n"
       
   366 							   "wMaxPacketSize = <%u>\n"
       
   367 							   "bInterval = <%u>\n",
       
   368 							   pEndpointDescriptor->bLength,
       
   369 							   pEndpointDescriptor->bDescriptorType,
       
   370 							   pEndpointDescriptor->bEndpointAddress,
       
   371 							   pEndpointDescriptor->bmAttributes,
       
   372 							   pEndpointDescriptor->wMaxPacketSize,
       
   373 							   pEndpointDescriptor->bInterval);
       
   374 						}
       
   375 					break;
       
   376 				default:
       
   377 					break;
       
   378 					}
       
   379 				}
       
   380 			data += ulDescLength;
       
   381 			rl -= ulDescLength;
       
   382 			}
       
   383 		}
       
   384 	PRINT_IF_VERBOSE("\n");
       
   385 	}
       
   386 
       
   387 
       
   388 static void GetStringDescriptor()
       
   389 	{
       
   390 	CHAR szBuffer[MAX_DESCRIPTOR_BUFFER_SIZE] = "";
       
   391 	USB_STRING_DESCRIPTOR* pStringDescriptor = NULL;
       
   392 	DWORD dwByteCount = MAX_DESCRIPTOR_BUFFER_SIZE;
       
   393 
       
   394 	memset(szBuffer, 0, sizeof(szBuffer));
       
   395 
       
   396 	// Get string descriptor
       
   397 	dwRC = g_UsbDev.GetStringDescriptor((USB_STRING_DESCRIPTOR*) szBuffer,
       
   398 										dwByteCount, 1, 0);
       
   399 	PRINT_IF_VERBOSE1("CUsbIo::GetStringDescriptor returned <0x%X>\n", dwRC);
       
   400 
       
   401 	if (dwRC == USBIO_ERR_SUCCESS)
       
   402 		{
       
   403 		pStringDescriptor = (USB_STRING_DESCRIPTOR*) szBuffer;
       
   404 		if (VerboseMode)
       
   405 			{
       
   406 			printf("\nSTRING DESCRIPTOR:\n"
       
   407 				   "bLength = <%u>\n"
       
   408 				   "bDescriptorType = <%u>\n"
       
   409 				   "bString = <",							// output continues below!
       
   410 				   pStringDescriptor->bLength,
       
   411 				   pStringDescriptor->bDescriptorType);
       
   412 			}
       
   413 		INT i = 0;
       
   414 		CHAR* Ptr = szBuffer;
       
   415 		for (i = 2, Ptr += 2;
       
   416 			 i < pStringDescriptor->bLength;
       
   417 			 i += 2, Ptr += 2)
       
   418 			{
       
   419 			PRINT_IF_VERBOSE1("%c", *Ptr);
       
   420 			}
       
   421 		PRINT_IF_VERBOSE(">\n\n");
       
   422 		}
       
   423 	}
       
   424 
       
   425 
       
   426 static void SetConfiguration()
       
   427 	{
       
   428 	USBIO_SET_CONFIGURATION SetConfig;
       
   429 
       
   430 	memset(&SetConfig, 0, sizeof(USBIO_SET_CONFIGURATION));
       
   431 
       
   432 	// Set the first configuration as active
       
   433 	SetConfig.ConfigurationIndex = 0;
       
   434 	SetConfig.NbOfInterfaces = 1;
       
   435 	SetConfig.InterfaceList[0].InterfaceIndex = 0;
       
   436 	SetConfig.InterfaceList[0].AlternateSettingIndex = 0;
       
   437 	SetConfig.InterfaceList[0].MaximumTransferSize = KBufferSize;
       
   438 	dwRC = g_UsbDev.SetConfiguration(&SetConfig);
       
   439 	PRINT_IF_VERBOSE1("CUsbIo::SetConfiguration returned <0x%X>\n", dwRC);
       
   440 	}
       
   441 
       
   442 
       
   443 static void GetConfigurationInfo()
       
   444 	{
       
   445 	USBIO_CONFIGURATION_INFO ConfigInfo;
       
   446 	USHORT i = 0;
       
   447 
       
   448 	memset(&ConfigInfo, 0, sizeof(USBIO_CONFIGURATION_INFO));
       
   449 
       
   450 	dwRC = g_UsbDev.GetConfigurationInfo(&ConfigInfo);
       
   451 	PRINT_IF_VERBOSE1("CUsbIo::GetConfigurationInfo returned <0x%X>\n", dwRC);
       
   452 
       
   453 	if (dwRC == USBIO_ERR_SUCCESS)
       
   454 		{
       
   455 		if (VerboseMode)
       
   456 			{
       
   457 			printf("\nCONFIGURATION INFO:\n"
       
   458 				   "NbOfInterfaces = <%lu>\n"
       
   459 				   "NbOfPipes = <%lu>\n",
       
   460 				   ConfigInfo.NbOfInterfaces,
       
   461 				   ConfigInfo.NbOfPipes);
       
   462 			}
       
   463 		for (i = 0; i < ConfigInfo.NbOfInterfaces; i++)
       
   464 			{
       
   465 			if (VerboseMode)
       
   466 				{
       
   467 				printf("\nINTERFACE <%u>:\n", i + 1);
       
   468 				printf("InterfaceNumber = <%u>\n"
       
   469 					   "AlternateSetting = <%u>\n"
       
   470 					   "Class = <%u>\n"
       
   471 					   "SubClass = <%u>\n"
       
   472 					   "Protocol = <%u>\n"
       
   473 					   "NumberOfPipes = <%u>\n"
       
   474 					   "reserved1 = <%u>\n"
       
   475 					   "reserved2 = <%u>\n",
       
   476 					   ConfigInfo.InterfaceInfo[i].InterfaceNumber,
       
   477 					   ConfigInfo.InterfaceInfo[i].AlternateSetting,
       
   478 					   ConfigInfo.InterfaceInfo[i].Class,
       
   479 					   ConfigInfo.InterfaceInfo[i].SubClass,
       
   480 					   ConfigInfo.InterfaceInfo[i].Protocol,
       
   481 					   ConfigInfo.InterfaceInfo[i].NumberOfPipes,
       
   482 					   ConfigInfo.InterfaceInfo[i].reserved1,
       
   483 					   ConfigInfo.InterfaceInfo[i].reserved2);
       
   484 				}
       
   485 			}
       
   486 		for (i = 0; i < ConfigInfo.NbOfPipes; i++)
       
   487 			{
       
   488 			PRINT_IF_VERBOSE("\n");
       
   489 			if ((ConfigInfo.PipeInfo[i].PipeType == PipeTypeBulk) &&
       
   490 				!(ConfigInfo.PipeInfo[i].EndpointAddress & 0x80))
       
   491 				{
       
   492 				PRINT_IF_VERBOSE("Bulk OUT pipe found:\n");
       
   493 				g_ucBulkOutEndpoint = ConfigInfo.PipeInfo[i].EndpointAddress;
       
   494 				maxOutPacketSize = ConfigInfo.PipeInfo[i].MaximumPacketSize;
       
   495 				}
       
   496 			else if ((ConfigInfo.PipeInfo[i].PipeType == PipeTypeBulk) &&
       
   497 					 (ConfigInfo.PipeInfo[i].EndpointAddress & 0x80))
       
   498 				{
       
   499 				PRINT_IF_VERBOSE("Bulk IN pipe found:\n");
       
   500 				g_ucBulkInEndpoint = ConfigInfo.PipeInfo[i].EndpointAddress;
       
   501 				}
       
   502 			if (VerboseMode)
       
   503 				{
       
   504 				printf("PIPE <%u>\n", i + 1);
       
   505 				printf("PipeType = <%d>\n"
       
   506 					   "MaximumTransferSize = <%lu>\n"
       
   507 					   "MaximumPacketSize = <%u>\n"
       
   508 					   "EndpointAddress = <%u>\n"
       
   509 					   "Interval = <%u>\n"
       
   510 					   "InterfaceNumber = <%u>\n"
       
   511 					   "reserved1 = <%u>\n"
       
   512 					   "reserved2 = <%u>\n"
       
   513 					   "reserved3 = <%u>\n",
       
   514 					   ConfigInfo.PipeInfo[i].PipeType,
       
   515 					   ConfigInfo.PipeInfo[i].MaximumTransferSize,
       
   516 					   ConfigInfo.PipeInfo[i].MaximumPacketSize,
       
   517 					   ConfigInfo.PipeInfo[i].EndpointAddress,
       
   518 					   ConfigInfo.PipeInfo[i].Interval,
       
   519 					   ConfigInfo.PipeInfo[i].InterfaceNumber,
       
   520 					   ConfigInfo.PipeInfo[i].reserved1,
       
   521 					   ConfigInfo.PipeInfo[i].reserved2,
       
   522 					   ConfigInfo.PipeInfo[i].reserved3);
       
   523 				}
       
   524 			}
       
   525 		}
       
   526 	PRINT_IF_VERBOSE("\n");
       
   527 	}
       
   528 
       
   529 
       
   530 static void OpenPipes()
       
   531 	{
       
   532 	CUsbIo::DestroyDeviceList(g_DevList);
       
   533 
       
   534 	// Enumerate attached USB devices supported by USBIO
       
   535 	g_DevList = CUsbIo::CreateDeviceList(&g_UsbioID);
       
   536 
       
   537 	// Create the bulk OUT pipe
       
   538 	dwRC = g_BulkOutPipe.Bind(0, g_ucBulkOutEndpoint, g_DevList, &g_UsbioID);
       
   539 	PRINT_IF_VERBOSE1("CUsbIoPipe::Bind (Bulk OUT) returned <0x%X>\n", dwRC);
       
   540 
       
   541 	if (dwRC == USBIO_ERR_SUCCESS)
       
   542 		{
       
   543 		// Create the bulk IN pipe
       
   544 		dwRC = g_BulkInPipe.Bind(0, g_ucBulkInEndpoint, g_DevList, &g_UsbioID);
       
   545 		PRINT_IF_VERBOSE1("CUsbIoPipe::Bind (Bulk IN) returned <0x%X>\n", dwRC);
       
   546 		}
       
   547 	PRINT_IF_VERBOSE("\n");
       
   548 	}
       
   549 
       
   550 
       
   551 static void ClosePipes()
       
   552 	{
       
   553 	// Close down the bulk OUT pipe
       
   554 	dwRC = g_BulkOutPipe.Unbind();
       
   555 	PRINT_IF_VERBOSE1("CUsbIoPipe::Unbind (Bulk OUT) returned <0x%X>\n", dwRC);
       
   556 
       
   557 	if (dwRC == USBIO_ERR_SUCCESS)
       
   558 		{
       
   559 		// Close down the bulk IN pipe
       
   560 		dwRC = g_BulkInPipe.Unbind();
       
   561 		PRINT_IF_VERBOSE1("CUsbIoPipe::Unbind (Bulk IN) returned <0x%X>\n", dwRC);
       
   562 		}
       
   563 	}
       
   564 
       
   565 
       
   566 static void ReceiveVersion()
       
   567 	{
       
   568 	// Here we (hope to) read an 8 byte packet containing the T_USB version.
       
   569 	printf("* Waiting for T_USB version packet to arrive...");
       
   570 
       
   571 	// The first 4 bytes are interpreted as an int32 value.
       
   572 	DWORD bytes_read = 0;
       
   573 	g_Buf.NumberOfBytesToTransfer = KPreambleLength;
       
   574 	g_BulkInPipe.Read(&g_Buf);
       
   575 	dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
       
   576 	printf(" done.\n");
       
   577 	bytes_read = g_Buf.BytesTransferred;
       
   578 	if (dwRC == USBIO_ERR_SUCCESS)
       
   579 		{
       
   580 		if (bytes_read < KPreambleLength)
       
   581 			{
       
   582 			printf("* Read less bytes (%d) than expected (%d).\n",
       
   583 				   bytes_read, KPreambleLength);
       
   584 			dwRC = USBIO_ERR_FAILED;
       
   585 			return;
       
   586 			}
       
   587 		}
       
   588 	else
       
   589 		{
       
   590 		printf("\n* Error: CUsbIoPipe::Read (version) returned <0x%X>\n", dwRC);
       
   591 		return;
       
   592 		}
       
   593 	// First make sure it's actually the version packet, and not
       
   594 	// a data preamble packet of an old T_USB.
       
   595 	if (!(Data[4] == 'V' &&
       
   596 		  Data[5] == 'e' &&
       
   597 		  Data[6] == 'r' &&
       
   598 		  Data[7] == 's'))
       
   599 		{
       
   600 		printf("* Inadequate version of T_USB: no version packet was sent (we need at least %d)\n",
       
   601 			   KTusbVersion);
       
   602 		dwRC = USBIO_ERR_FAILED;
       
   603 		return;
       
   604 		}
       
   605 	DWORD tusb_version = *((ULONG*) Data);						// first 4 bytes
       
   606 	if (tusb_version < KTusbVersion)
       
   607 		{
       
   608 		printf("* Inadequate version of T_USB: %d (we need at least %d)\n",
       
   609 			   tusb_version, KTusbVersion);
       
   610 		dwRC = USBIO_ERR_FAILED;
       
   611 		return;
       
   612 		}
       
   613 	printf("* Suitable version of T_USB found: %d.\n", tusb_version);
       
   614 	}
       
   615 
       
   616 
       
   617 static void SendVersion()
       
   618 	{
       
   619 	// Here we send an 8 byte packet containing USBRFLCT's + USBIO's versions.
       
   620 	printf("* Sending our version packet to T_USB...");
       
   621 
       
   622 	DWORD bytes_written = 0;
       
   623 	g_Buf.NumberOfBytesToTransfer = KPreambleLength;
       
   624 	Data[0] = VERSION_MAJOR;
       
   625 	Data[1] = VERSION_MINOR;
       
   626 	Data[2] = VERSION_MICRO;
       
   627 	Data[3] = USBIO_VERSION_MAJOR;
       
   628 	Data[4] = USBIO_VERSION_MINOR;
       
   629 	g_BulkOutPipe.Write(&g_Buf);
       
   630 	dwRC = g_BulkOutPipe.WaitForCompletion(&g_Buf, INFINITE);
       
   631 	printf(" done.\n");
       
   632 	bytes_written = g_Buf.BytesTransferred;
       
   633 	if (dwRC == USBIO_ERR_SUCCESS)
       
   634 		{
       
   635 		if (bytes_written < KPreambleLength)
       
   636 			{
       
   637 			printf("* Wrote less bytes (%d) than requested (%d).\n",
       
   638 				   bytes_written, KPreambleLength);
       
   639 			dwRC = USBIO_ERR_FAILED;
       
   640 			}
       
   641 		}
       
   642 	else
       
   643 		{
       
   644 		printf("\n* Error: CUsbIoPipe::Write (version) returned <0x%X>\n", dwRC);
       
   645 		}
       
   646 	}
       
   647 
       
   648 
       
   649 static void ExchangeVersions()
       
   650 	{
       
   651 	SendVersion();
       
   652 	if (dwRC != USBIO_ERR_SUCCESS)
       
   653 		return;
       
   654 	ReceiveVersion();
       
   655 	}
       
   656 
       
   657 
       
   658 static void GetLength()
       
   659 	{
       
   660 	// The first two bytes are interpreted as a length value.
       
   661 	DWORD bytes_read = KPreambleLength;
       
   662 	g_Buf.NumberOfBytesToTransfer = KPreambleLength;
       
   663 
       
   664 	g_BulkInPipe.Read(&g_Buf);
       
   665 	dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
       
   666 	bytes_read = g_Buf.BytesTransferred;
       
   667 
       
   668 	if (dwRC == USBIO_ERR_SUCCESS)
       
   669 		{
       
   670 		if (bytes_read < KPreambleLength)
       
   671 			{
       
   672 			printf("* Read less bytes (%d) than expected (%d).\n",
       
   673 				   bytes_read, KPreambleLength);
       
   674 			dwRC = USBIO_ERR_FAILED;
       
   675 			return;
       
   676 			}
       
   677 		}
       
   678 	else
       
   679 		{
       
   680 		printf("\n* Error: CUsbIoPipe::Read (length) returned <0x%X>\n", dwRC);
       
   681 		return;
       
   682 		}
       
   683 	Length = *((ULONG*) Data);								// first 4 bytes
       
   684 	if (Length > KBufferSize)
       
   685 		{
       
   686 		printf("* This is too much: %d (our buffer is too small: %d)\n",
       
   687 			   Length, KBufferSize);
       
   688 		dwRC = USBIO_ERR_FAILED;
       
   689 		}
       
   690 	if (VerboseMode)
       
   691 		{
       
   692 		printf("* Just read %d bytes, now assuming transfer length is %d bytes.\n",
       
   693 			   bytes_read, Length);
       
   694 		}
       
   695 	else if (TransferMode == EReceiveOnly || TransferMode == ETransmitOnly)
       
   696 		{
       
   697 		printf("* Single transfer size: %d bytes.\n", Length);
       
   698 		}
       
   699 	}
       
   700 
       
   701 
       
   702 static void ReadData()
       
   703 	{
       
   704 	// We have to setup a read for at least one byte in order to get
       
   705 	// the host to issue IN tokens for our zero-byte read:
       
   706 	if (Length == 0)
       
   707 		g_Buf.NumberOfBytesToTransfer = 1;
       
   708 	else
       
   709 		g_Buf.NumberOfBytesToTransfer = Length;
       
   710 
       
   711 	g_BulkInPipe.Read(&g_Buf);
       
   712 	dwRC = g_BulkInPipe.WaitForCompletion(&g_Buf, INFINITE);
       
   713 	DWORD bytes_read = g_Buf.BytesTransferred;
       
   714 
       
   715 	if (dwRC != USBIO_ERR_SUCCESS)
       
   716 		{
       
   717 		printf("\n* Error: CUsbIoPipe::Read (data) returned <0x%X>\n", dwRC);
       
   718 		}
       
   719 	else
       
   720 		{
       
   721 		if (bytes_read != Length)
       
   722 			{
       
   723 			printf("* Read more/less bytes (%d) than expected (%d).\n",
       
   724 				   bytes_read, Length);
       
   725 			dwRC = USBIO_ERR_FAILED;
       
   726 			}
       
   727 		else
       
   728 			{
       
   729 			PRINT_IF_VERBOSE1("* Read %d bytes.\n", Length);
       
   730 			}
       
   731 		}
       
   732 	}
       
   733 
       
   734 
       
   735 static void WriteData()
       
   736 	{
       
   737 	DWORD bytes_written = Length;
       
   738 
       
   739 	g_Buf.NumberOfBytesToTransfer = bytes_written;
       
   740 
       
   741 	g_BulkOutPipe.Write(&g_Buf);
       
   742 	dwRC = g_BulkOutPipe.WaitForCompletion(&g_Buf, INFINITE);
       
   743 	if (ZlpMode && (Length >= maxOutPacketSize) && ((Length % maxOutPacketSize) == 0))
       
   744 	{
       
   745 		// writes a zero length packet
       
   746 		g_BulkOutPipe.Write(&g_ZlpBuf);
       
   747 		dwRC = g_BulkOutPipe.WaitForCompletion(&g_ZlpBuf, INFINITE);
       
   748 	}
       
   749 
       
   750 
       
   751 	bytes_written = g_Buf.BytesTransferred;
       
   752 
       
   753 	if (dwRC == USBIO_ERR_SUCCESS)
       
   754 		{
       
   755 		PRINT_IF_VERBOSE1("* Wrote %d bytes.\n", bytes_written);
       
   756 		}
       
   757 	else
       
   758 		{
       
   759 		printf("\n* Error: CUsbIoPipe::Write returned <0x%X>\n", dwRC);
       
   760 		}
       
   761 	}
       
   762 
       
   763 
       
   764 void PrintStats()
       
   765 	{
       
   766 	static DWORD loop = 0;									// the loop counter
       
   767 	static double xfer_size = 0;							// the total transfer amount so far
       
   768 	time_t t_1 = time(NULL);								// current time
       
   769 	double t_diff = difftime(t_1, T_0);						// this yields current seconds since start
       
   770 	xfer_size += (KPreambleLength + (2 * Length)) * KLoopModeDisplayUpdate;	//
       
   771 	double xfer_rate = xfer_size / t_diff;					// mean transfer rate since start
       
   772 	loop += KLoopModeDisplayUpdate;
       
   773 	printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s  \r",
       
   774 		   loop, Length, xfer_size, xfer_rate);
       
   775 	}
       
   776 
       
   777 
       
   778 void PrintStatsEveryLoop()
       
   779 	{
       
   780 	static DWORD loop = 0;									// the loop counter
       
   781 	static double xfer_size = 0;							// the total transfer amount so far
       
   782 	time_t t_1 = time(NULL);								// current time
       
   783 	double t_diff = difftime(t_1, T_0);						// this yields current seconds since start
       
   784 	xfer_size += (KPreambleLength + (2 * Length));			//
       
   785 	double xfer_rate = xfer_size / t_diff;					// mean transfer rate since start
       
   786 	printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s  \r",
       
   787 		   ++loop, Length, xfer_size, xfer_rate);
       
   788 	}
       
   789 
       
   790 
       
   791 void PrintUnidirStats()
       
   792 	{
       
   793 	static DWORD loop = 0;									// the loop counter
       
   794 	static double xfer_size = 0;							// the total transfer amount so far
       
   795 	time_t t_1 = time(NULL);								// current time
       
   796 	double t_diff = difftime(t_1, T_0);						// this yields current seconds since start
       
   797 	xfer_size += Length * KUniModeDisplayUpdate;
       
   798 	double xfer_rate = xfer_size / t_diff;					// mean transfer rate since start
       
   799 	loop += KUniModeDisplayUpdate;
       
   800 	printf("* Iter: %d (%d bytes) Total: %.0f bytes Rate: %.0f bytes/s  \r",
       
   801 		   loop, Length, xfer_size, xfer_rate);
       
   802 	}
       
   803 
       
   804 
       
   805 static void LoopTransfer()
       
   806 	{
       
   807 	printf("* Loop Transfers -- reading & writing alternately.\n");
       
   808 
       
   809 	T_0 = time(NULL);										// starting time
       
   810 
       
   811 	while (dwRC == USBIO_ERR_SUCCESS)
       
   812 		{
       
   813 		static DWORD n = 0;
       
   814 
       
   815 		// First we get the length (+ the packet size)
       
   816 		GetLength();
       
   817 
       
   818 		if (dwRC == USBIO_ERR_SUCCESS)
       
   819 			{
       
   820 			// Then we read 'Length' bytes
       
   821 			ReadData();
       
   822 			}
       
   823 
       
   824 		if (dwRC == USBIO_ERR_SUCCESS)
       
   825 			{
       
   826 			// Now we send the received data back to the client.
       
   827 			WriteData();
       
   828 			}
       
   829 
       
   830 		if (dwRC == USBIO_ERR_SUCCESS)
       
   831 			{
       
   832 			// Finally, sometimes we print some statistics
       
   833 			if (TransferMode == ELoopDebug)
       
   834 				PrintStatsEveryLoop();
       
   835 			else if ((++n % KLoopModeDisplayUpdate) == 0)
       
   836 				PrintStats();
       
   837 			}
       
   838 		}
       
   839 	}
       
   840 
       
   841 
       
   842 static void ReceiveOnlyTransfer()
       
   843 	{
       
   844 	printf("* Receive-only transfers (IN).\n");
       
   845 
       
   846 	// First (and only once) we get the transfer length (+ the packet size)
       
   847 	GetLength();
       
   848 
       
   849 	T_0 = time(NULL);										// starting time
       
   850 
       
   851 	while (dwRC == USBIO_ERR_SUCCESS)
       
   852 		{
       
   853 		static DWORD n = -1;
       
   854 		static DWORD pktNum;
       
   855 
       
   856 		// Then we read 'Length' bytes
       
   857 		ReadData();
       
   858 		pktNum = *(DWORD *)&Data;
       
   859 		if (pktNum != ++n)
       
   860 			{
       
   861 			printf ("\n* Error: rcv'd wrong pkt number: 0x%x (expected: 0x%x)\n", pktNum, n);
       
   862 			// reset from the received packet number, so that ...
       
   863 			// if a packet is lost or duplicated a single error is reported
       
   864 			n = pktNum;
       
   865 			}
       
   866 		// Finally, sometimes we print some statistics
       
   867 		if ((n % KUniModeDisplayUpdate) == 0)
       
   868 			PrintUnidirStats();
       
   869 		}
       
   870 	}
       
   871 
       
   872 
       
   873 static void TransmitOnlyTransfer()
       
   874 	{
       
   875 	printf("* Transmit-only transfers (OUT).\n");
       
   876 
       
   877 	// First (and only once) we get the transfer length (+ the packet size)
       
   878 	GetLength();
       
   879 
       
   880 	T_0 = time(NULL);										// starting time
       
   881 
       
   882 	while (dwRC == USBIO_ERR_SUCCESS)
       
   883 		{
       
   884 		static DWORD n = 0;
       
   885 		// First the packet number is put into the first four bytes
       
   886 		*(DWORD *)&Data = n++;
       
   887 		// Then we write 'Length' bytes
       
   888 		WriteData();
       
   889 
       
   890 		// Finally, sometimes we print some statistics
       
   891 		if ((n % KUniModeDisplayUpdate) == 0)
       
   892 			PrintUnidirStats();
       
   893 		}
       
   894 	}
       
   895 
       
   896 
       
   897 static void DoTransfers()
       
   898 	{
       
   899 	switch (TransferMode)
       
   900 		{
       
   901 	case ELoop:
       
   902 	case ELoopDebug:
       
   903 		LoopTransfer();
       
   904 		break;
       
   905 	case EReceiveOnly:
       
   906 		ReceiveOnlyTransfer();
       
   907 		break;
       
   908 	case ETransmitOnly:
       
   909 		TransmitOnlyTransfer();
       
   910 		break;
       
   911 	default:
       
   912 		dwRC = -1;
       
   913 		break;
       
   914 		}
       
   915 	}
       
   916 
       
   917 
       
   918 static void Delay(int milliseconds)
       
   919 	{
       
   920 	printf("* Short wait... ");
       
   921 	Sleep(milliseconds);
       
   922 	printf("done.\n");
       
   923 	}
       
   924 
       
   925 
       
   926 static void PrintHello()
       
   927 	{
       
   928 	printf("*--------------------------------------------------\n");
       
   929 	printf("* USBRFLCT v%d.%d.%d (for use with USBRFLCT.SYS v%d.%d)\n",
       
   930 		   VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO,
       
   931 		   USBIO_VERSION_MAJOR, USBIO_VERSION_MINOR);
       
   932 	printf("* USB Reflector Test Program / T_USB Host-side Part\n");
       
   933 	printf("*   Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).\n");
       
   934 	printf("*--------------------------------------------------\n");
       
   935 	}
       
   936 
       
   937 
       
   938 int main(int argc, char* argv[])
       
   939 	{
       
   940 	PrintHello();
       
   941 
       
   942 	if (ProcessCmdLine(argc, argv) != 0)
       
   943 		return -1;
       
   944 
       
   945 	OpenUsbDevice();
       
   946 
       
   947 	if (dwRC == USBIO_ERR_SUCCESS)
       
   948 		{
       
   949 		GetDeviceDescriptor();
       
   950 		}
       
   951 	if (dwRC == USBIO_ERR_SUCCESS)
       
   952 		{
       
   953 		GetConfigurationDescriptor();
       
   954 		}
       
   955 	if (dwRC == USBIO_ERR_SUCCESS)
       
   956 		{
       
   957 		GetStringDescriptor();
       
   958 		}
       
   959 	if (dwRC == USBIO_ERR_SUCCESS)
       
   960 		{
       
   961 		SetConfiguration();
       
   962 		}
       
   963 	if (dwRC == USBIO_ERR_SUCCESS)
       
   964 		{
       
   965 		// In order to give the USB device-side program (t_usb)
       
   966 		// enough time after getting configured to carry out
       
   967 		// some device tests, we wait here for a short while
       
   968 		// before proceeding:
       
   969 		Delay(2000);
       
   970 		GetConfigurationInfo();
       
   971 		}
       
   972 	if (dwRC == USBIO_ERR_SUCCESS)
       
   973 		{
       
   974 		OpenPipes();
       
   975 		}
       
   976 	if (dwRC == USBIO_ERR_SUCCESS)
       
   977 		{
       
   978 		ExchangeVersions();
       
   979 		}
       
   980 	if (dwRC == USBIO_ERR_SUCCESS)
       
   981 		{
       
   982 		DoTransfers();
       
   983 		}
       
   984 	if (dwRC == USBIO_ERR_SUCCESS)
       
   985 		{
       
   986 		ClosePipes();
       
   987 		}
       
   988 
       
   989 	CloseUsbDevice();
       
   990 
       
   991 	return 0;
       
   992 	}
       
   993 
       
   994 
       
   995 // --eof