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