os/kernelhwsrv/kerneltest/e32test/device/t_usbco2.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/device/t_usbco2.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1853 @@
     1.4 +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32test/device/t_usbco2.cpp
    1.18 +// USB Test Program T_USB, functional part.
    1.19 +// Device-side part, to work against USBRFLCT running on the host.
    1.20 +// 
    1.21 +//
    1.22 +
    1.23 +#include <e32hal.h>
    1.24 +#include <e32uid.h>
    1.25 +#include <hal.h>
    1.26 +
    1.27 +#include "t_usb.h"											// CActiveConsole, CActiveRW
    1.28 +#include "t_usblib.h"										// Helpers
    1.29 +
    1.30 +
    1.31 +_LIT(KUsbLddFilename, "eusbc");								// .ldd assumed - it's a filename
    1.32 +_LIT(KOtgdiLddFilename, "otgdi");
    1.33 +_LIT(KUsbDeviceName, "Usbc");
    1.34 +_LIT(KFileName, "\\T_USBFILE.BIN");
    1.35 +_LIT(KActivePanic, "T_USB");
    1.36 +
    1.37 +static const TUint32 KTusbVersion = 20070524;				// just an edit date really
    1.38 +static const TUint8 KUsbrflctVersionMajor = 1;				// the version we're compatible with
    1.39 +static const TUint8 KUsbrflctVersionMinor = 5;
    1.40 +static const TUint8 KUsbrflctVersionMicro = 0;
    1.41 +
    1.42 +static const TInt KMaxFileSize = 100 * 1024 * 1024;			// 100MB (requires at least 128MB card)
    1.43 +static const TInt KInitialBufSz = 0;
    1.44 +static const TInt stridx1 = 0xCC;
    1.45 +static const TInt stridx2 = 0xEE;
    1.46 +
    1.47 +//
    1.48 +// --- class CActiveConsole ---------------------------------------------------------
    1.49 +//
    1.50 +
    1.51 +CActiveConsole::CActiveConsole(CConsoleBase* aConsole, TBool aVerboseOutput)
    1.52 +	: CActive(EPriorityNormal),
    1.53 +	  iConsole(aConsole),
    1.54 +	  iRW(NULL),
    1.55 +	  iBufferSizeChosen(EFalse),
    1.56 +	  iBandwidthPriorityChosen(EFalse),
    1.57 +	  iDMAChosen(EFalse),
    1.58 +	  iDoubleBufferingChosen(EFalse),
    1.59 +	  iSoftwareConnect(EFalse),
    1.60 +	  iHighSpeed(EFalse),
    1.61 +	  iOtg(EFalse),
    1.62 +	  iVerbose(aVerboseOutput)
    1.63 +	{}
    1.64 +
    1.65 +
    1.66 +CActiveConsole* CActiveConsole::NewLC(CConsoleBase* aConsole, TBool aVerboseOutput)
    1.67 +	{
    1.68 +	CActiveConsole* self = new (ELeave) CActiveConsole(aConsole, aVerboseOutput);
    1.69 +	CleanupStack::PushL(self);
    1.70 +	self->ConstructL();
    1.71 +	return self;
    1.72 +	}
    1.73 +
    1.74 +
    1.75 +CActiveConsole* CActiveConsole::NewL(CConsoleBase* aConsole, TBool aVerboseOutput)
    1.76 +	{
    1.77 +	CActiveConsole* self = NewLC(aConsole, aVerboseOutput);
    1.78 +	CleanupStack::Pop();
    1.79 +	return self;
    1.80 +	}
    1.81 +
    1.82 +
    1.83 +void CActiveConsole::ConstructL()
    1.84 +	{
    1.85 +	CActiveScheduler::Add(this);
    1.86 +
    1.87 +	// Load logical driver (LDD)
    1.88 +	// (There's no physical driver (PDD) with USB: it's a kernel extension DLL which
    1.89 +	//  was already loaded at boot time.)
    1.90 +	TInt r = User::LoadLogicalDevice(KUsbLddFilename);
    1.91 +	if (r != KErrNone && r != KErrAlreadyExists)
    1.92 +		{
    1.93 +		TUSB_PRINT1("Error %d on loading USB LDD", r);
    1.94 +		User::Leave(-1);
    1.95 +		return;
    1.96 +		}
    1.97 +	TUSB_PRINT("Successfully loaded USB LDD");
    1.98 +
    1.99 +	// Open USB channel
   1.100 +	r = iPort.Open(0);
   1.101 +	if (r != KErrNone)
   1.102 +		{
   1.103 +		TUSB_PRINT1("Error %d on opening USB port", r);
   1.104 +		User::Leave(-1);
   1.105 +		return;
   1.106 +		}
   1.107 +	TUSB_PRINT("Successfully opened USB port");
   1.108 +
   1.109 +	// Create Reader/Writer active object
   1.110 +	iRW = CActiveRW::NewL(iConsole, &iPort, iVerbose);
   1.111 +	if (!iRW)
   1.112 +		{
   1.113 +		TUSB_PRINT("Failed to create reader/writer");
   1.114 +		User::Leave(-1);
   1.115 +		return;
   1.116 +		}
   1.117 +	TUSB_PRINT("Created reader/writer");
   1.118 +
   1.119 +	// Check for OTG support
   1.120 +	TBuf8<KUsbDescSize_Otg> otg_desc;
   1.121 +	r = iPort.GetOtgDescriptor(otg_desc);
   1.122 +	if (!(r == KErrNotSupported || r == KErrNone))
   1.123 +		{
   1.124 +		TUSB_PRINT1("Error %d while fetching OTG descriptor", r);
   1.125 +		User::Leave(-1);
   1.126 +		return;
   1.127 +		}
   1.128 +	iOtg = (r != KErrNotSupported) ? ETrue : EFalse;
   1.129 +
   1.130 +	// On an OTG device we have to start the OTG driver, otherwise the Client
   1.131 +	// stack will remain disabled forever.
   1.132 +	if (iOtg)
   1.133 +		{
   1.134 +		TUSB_PRINT("Running on OTG device: loading OTG driver");
   1.135 +		r = User::LoadLogicalDevice(KOtgdiLddFilename);
   1.136 +		if (r != KErrNone)
   1.137 +			{
   1.138 +			TUSB_PRINT1("Error %d on loading OTG LDD", r);
   1.139 +			User::Leave(-1);
   1.140 +			return;
   1.141 +			}
   1.142 +		r = iOtgPort.Open();
   1.143 +		if (r != KErrNone)
   1.144 +			{
   1.145 +			TUSB_PRINT1("Error %d on opening OTG port", r);
   1.146 +			User::Leave(-1);
   1.147 +			return;
   1.148 +			}
   1.149 +		r = iOtgPort.StartStacks();
   1.150 +		if (r != KErrNone)
   1.151 +			{
   1.152 +			TUSB_PRINT1("Error %d on starting USB stack", r);
   1.153 +			User::Leave(-1);
   1.154 +			return;
   1.155 +			}
   1.156 +		}
   1.157 +	}
   1.158 +
   1.159 +
   1.160 +TInt CActiveConsole::SetupInterface()
   1.161 +	{
   1.162 +	// Query the USB device/Setup the USB interface
   1.163 +	TInt r = QueryUsbClientL();
   1.164 +	if (r != KErrNone)
   1.165 +		{
   1.166 +		TUSB_PRINT1("Interface setup failed", r);
   1.167 +		return r;
   1.168 +		}
   1.169 +	TUSB_PRINT("Interface successfully set up");
   1.170 +
   1.171 +	// Change some descriptors to contain suitable values
   1.172 +	r = SetupDescriptors();
   1.173 +	if (r != KErrNone)
   1.174 +		{
   1.175 +		TUSB_PRINT1("Descriptor setup failed", r);
   1.176 +		return r;
   1.177 +		}
   1.178 +
   1.179 +	// Create device state active object
   1.180 +	iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(iConsole, &iPort, iVerbose);
   1.181 +	if (!iDeviceStateNotifier)
   1.182 +		{
   1.183 +		TUSB_PRINT("Failed to create device state notifier");
   1.184 +		return r;
   1.185 +		}
   1.186 +	iDeviceStateNotifier->Activate();
   1.187 +
   1.188 +	// Create endpoint stall status active object
   1.189 +	iStallNotifier = CActiveStallNotifier::NewL(iConsole, &iPort, iVerbose);
   1.190 +	if (!iStallNotifier)
   1.191 +		{
   1.192 +		TUSB_PRINT("Failed to create stall notifier");
   1.193 +		return r;
   1.194 +		}
   1.195 +	iStallNotifier->Activate();
   1.196 +
   1.197 +	return r;
   1.198 +	}
   1.199 +
   1.200 +
   1.201 +CActiveConsole::~CActiveConsole()
   1.202 +	{
   1.203 +	TUSB_VERBOSE_PRINT("CActiveConsole::~CActiveConsole()");
   1.204 +	Cancel();												// base class cancel -> calls our DoCancel
   1.205 +	delete iRW;												// destroy the reader/writer
   1.206 +	delete iDeviceStateNotifier;
   1.207 +	delete iStallNotifier;
   1.208 +	TInt r = iPort.RemoveStringDescriptor(stridx1);
   1.209 +	if (r != KErrNone)
   1.210 +		{
   1.211 +		TUSB_PRINT1("Error %d on string removal", r);
   1.212 +		}
   1.213 +	r = iPort.RemoveStringDescriptor(stridx2);
   1.214 +	if (r != KErrNone)
   1.215 +		{
   1.216 +		TUSB_PRINT1("Error %d on string removal", r);
   1.217 +		}
   1.218 +	if (iOtg)
   1.219 +		{
   1.220 +		TUSB_PRINT("Running on OTG device: unloading OTG driver");
   1.221 +		iOtgPort.StopStacks();
   1.222 +		iOtgPort.Close();
   1.223 +		r = User::FreeLogicalDevice(RUsbOtgDriver::Name());
   1.224 +		if (r != KErrNone)
   1.225 +			{
   1.226 +			TUSB_PRINT1("Error %d on freeing OTG LDD", r);
   1.227 +			}
   1.228 +		}
   1.229 +	iPort.Close();											// close USB channel
   1.230 +	r = User::FreeLogicalDevice(KUsbDeviceName);
   1.231 +	if (r != KErrNone)
   1.232 +		{
   1.233 +		TUSB_PRINT1("Error %d during unloading USB LDD", r);
   1.234 +		User::Leave(-1);
   1.235 +		return;
   1.236 +		}
   1.237 +	TUSB_PRINT("Successfully unloaded USB LDD");	
   1.238 +	}
   1.239 +
   1.240 +
   1.241 +void CActiveConsole::DoCancel()
   1.242 +	{
   1.243 +	TUSB_VERBOSE_PRINT("CActiveConsole::DoCancel()");
   1.244 +	iConsole->ReadCancel();
   1.245 +	}
   1.246 +
   1.247 +
   1.248 +void CActiveConsole::RunL()
   1.249 +	{
   1.250 +	TUSB_VERBOSE_PRINT("CActiveConsole::RunL()");
   1.251 +	ProcessKeyPressL(static_cast<TChar>(iConsole->KeyCode()));
   1.252 +	}
   1.253 +
   1.254 +
   1.255 +void CActiveConsole::RequestCharacter()
   1.256 +	{
   1.257 +	// A request is issued to the CConsoleBase to accept a character from the keyboard.
   1.258 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
   1.259 +	if (!iBufferSizeChosen)
   1.260 +		{
   1.261 +		iConsole->Printf(_L("\n"));
   1.262 +		iConsole->Printf(_L("++++ Choose max. Transfer Size ++++\n"));
   1.263 +		iConsole->Printf(_L("  '0' - Set up USB device for USBCV\n"));
   1.264 +		iConsole->Printf(_L("  '1' -   32 bytes\n"));
   1.265 +		iConsole->Printf(_L("  '2' - 1024 bytes\n"));
   1.266 +		iConsole->Printf(_L("  '3' -   64 kbytes\n"));
   1.267 +		iConsole->Printf(_L("  '4' -    1 Mbyte\n"));
   1.268 +		}
   1.269 +	else if (!iBandwidthPriorityChosen)
   1.270 +		{
   1.271 +		iConsole->Printf(_L("\n"));
   1.272 +		iConsole->Printf(_L("++++ Choose Bandwidth Priority ++++\n"));
   1.273 +		iConsole->Printf(_L("  '1' - Economical buffering - default\n"));
   1.274 +		iConsole->Printf(_L("  '2' - More memory than default buffering - Plus1\n"));
   1.275 +		iConsole->Printf(_L("  '3' - More memory than Plus1 buffering - Plus2\n"));
   1.276 +		iConsole->Printf(_L("  '4' - Maximum buffering\n"));
   1.277 +		}
   1.278 +	else if (!iDMAChosen)
   1.279 +		{
   1.280 +		iConsole->Printf(_L("\n"));
   1.281 +		iConsole->Printf(_L("++++ Choose Endpoint I/O Transfer Mode ++++\n"));
   1.282 +		iConsole->Printf(_L("  '1' - Interrupt Mode\n"));
   1.283 +		iConsole->Printf(_L("  '2' - DMA Mode (recommended)\n"));
   1.284 +		}
   1.285 +	else if (!iDoubleBufferingChosen)
   1.286 +		{
   1.287 +		iConsole->Printf(_L("\n"));
   1.288 +		iConsole->Printf(_L("++++ Choose Endpoint FIFO Mode ++++\n"));
   1.289 +		iConsole->Printf(_L("  '1' - Normal Buffering Mode\n"));
   1.290 +		iConsole->Printf(_L("  '2' - Double Buffering Mode (recommended)\n"));
   1.291 +		}
   1.292 +	else
   1.293 +		{
   1.294 +		iConsole->Printf(_L("\n"));
   1.295 +		iConsole->Printf(_L("++++ Select Program Option ++++\n"));
   1.296 +		iConsole->Printf(_L("  'L'oop test\n"));
   1.297 +		iConsole->Printf(_L("   Loop test with data 'C'ompare\n"));
   1.298 +		iConsole->Printf(_L("  'R'eceive-only test (we receive, host transmits)\n"));
   1.299 +		iConsole->Printf(_L("  'T'ransmit-only test\n"));
   1.300 +		iConsole->Printf(_L("   Receive and 'P'ut (write) to File\n"));
   1.301 +		iConsole->Printf(_L("   Transmit and 'G'et (read) from File\n"));
   1.302 +		iConsole->Printf(_L("   Signal Remote-'W'akeup to the host\n"));
   1.303 +		iConsole->Printf(_L("  'S'top current transfer\n"));
   1.304 +#ifdef WITH_DUMP_OPTION
   1.305 +		iConsole->Printf(_L("  'D'ump USB regs to debugout\n"));
   1.306 +#endif
   1.307 +		iConsole->Printf(_L("   Re'E'numerate device\n"));
   1.308 +		iConsole->Printf(_L("  'Q'uit this app\n"));
   1.309 +		}
   1.310 +	iConsole->Read(iStatus);
   1.311 +	SetActive();
   1.312 +	}
   1.313 +
   1.314 +
   1.315 +void CActiveConsole::ProcessKeyPressL(TChar aChar)
   1.316 +	{
   1.317 +	if (aChar == EKeyEscape)
   1.318 +		{
   1.319 +		RDebug::Print(_L("CActiveConsole: ESC key pressed -> stopping active scheduler..."));
   1.320 +		CActiveScheduler::Stop();
   1.321 +		return;
   1.322 +		}
   1.323 +	if (!iBufferSizeChosen)
   1.324 +		{
   1.325 +		// Set maximum buffer size from keypress
   1.326 +		switch (aChar)
   1.327 +			{
   1.328 +		case '0':
   1.329 +			// This is for creating a USB device that just enumerates,
   1.330 +			// to be used for compliance testing with USBCV.
   1.331 +			iRW->SetMaxBufSize(0);
   1.332 +			break;
   1.333 +		case '1':
   1.334 +			iRW->SetMaxBufSize(32);
   1.335 +			break;
   1.336 +		case '2':
   1.337 +			iRW->SetMaxBufSize(1024);
   1.338 +			break;
   1.339 +		case '3':
   1.340 +			iRW->SetMaxBufSize(64 * 1024);
   1.341 +			break;
   1.342 +		case '4':
   1.343 +			iRW->SetMaxBufSize(KMaxBufSize);
   1.344 +			break;
   1.345 +		default:
   1.346 +			TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
   1.347 +			goto request_char;
   1.348 +			}
   1.349 +		TUSB_PRINT1("Maximum buffer size set to %d bytes", iRW->MaxBufSize());
   1.350 +		iBufferSizeChosen = ETrue;
   1.351 +		}
   1.352 +	else if (!iBandwidthPriorityChosen)
   1.353 +		{
   1.354 +		// Set bandwidth priority from keypress
   1.355 +		switch (aChar)
   1.356 +			{
   1.357 +		case '1':
   1.358 +			iBandwidthPriority = EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault;
   1.359 +			TUSB_PRINT("Bandwith priority set to default");
   1.360 +			break;
   1.361 +		case '2':
   1.362 +			iBandwidthPriority = EUsbcBandwidthOUTPlus1 | EUsbcBandwidthINPlus1;
   1.363 +			TUSB_PRINT("Bandwith priority set to Plus1");
   1.364 +			break;
   1.365 +		case '3':
   1.366 +			iBandwidthPriority = EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2;
   1.367 +			TUSB_PRINT("Bandwith priority set to Plus2");
   1.368 +			break;
   1.369 +		case '4':
   1.370 +			iBandwidthPriority = EUsbcBandwidthINMaximum | EUsbcBandwidthOUTMaximum;
   1.371 +			TUSB_PRINT("Bandwith priority set to maximum");
   1.372 +			break;
   1.373 +		default:
   1.374 +			TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
   1.375 +			goto request_char;
   1.376 +			}
   1.377 +		TUSB_PRINT1("(Set to 0x%08X)", iBandwidthPriority);
   1.378 +		iBandwidthPriorityChosen = ETrue;
   1.379 +
   1.380 +		TUSB_PRINT("Configuring interface...");
   1.381 +		TInt r = SetupInterface();
   1.382 +		if (r != KErrNone)
   1.383 +			{
   1.384 +			TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
   1.385 +			CActiveScheduler::Stop();
   1.386 +			return;
   1.387 +			}
   1.388 +		}
   1.389 +	else if (!iDMAChosen)
   1.390 +		{
   1.391 +		// Set DMA mode from keypress
   1.392 +		switch (aChar)
   1.393 +			{
   1.394 +		case '1':
   1.395 +			TUSB_PRINT("- Trying to deallocate endpoint DMA:\n");
   1.396 +			DeAllocateEndpointDMA(EEndpoint1);
   1.397 +			DeAllocateEndpointDMA(EEndpoint2);
   1.398 +			break;
   1.399 +		case '2':
   1.400 +			TUSB_PRINT("- Trying to allocate endpoint DMA:\n");
   1.401 +			AllocateEndpointDMA(EEndpoint1);
   1.402 +			AllocateEndpointDMA(EEndpoint2);
   1.403 +			break;
   1.404 +		default:
   1.405 +			TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
   1.406 +			goto request_char;
   1.407 +			}
   1.408 +		iDMAChosen = ETrue;
   1.409 +		}
   1.410 +	else if (!iDoubleBufferingChosen)
   1.411 +		{
   1.412 +		// Set Double Buffering from keypress
   1.413 +		switch (aChar)
   1.414 +			{
   1.415 +		case '1':
   1.416 +			TUSB_PRINT("- Trying to deallocate Double Buffering:\n");
   1.417 +			DeAllocateDoubleBuffering(EEndpoint1);
   1.418 +			DeAllocateDoubleBuffering(EEndpoint2);
   1.419 +			break;
   1.420 +		case '2':
   1.421 +			TUSB_PRINT("- Trying to allocate Double Buffering:\n");
   1.422 +			AllocateDoubleBuffering(EEndpoint1);
   1.423 +			AllocateDoubleBuffering(EEndpoint2);
   1.424 +			break;
   1.425 +		default:
   1.426 +			TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
   1.427 +			goto request_char;
   1.428 +			}
   1.429 +		iDoubleBufferingChosen = ETrue;
   1.430 +
   1.431 +		// Everything chosen, so let's re-enumerate...
   1.432 +		TUSB_PRINT("Enumeration...");
   1.433 +		TInt r = ReEnumerate();
   1.434 +		if (r != KErrNone)
   1.435 +			{
   1.436 +			TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
   1.437 +			CActiveScheduler::Stop();
   1.438 +			return;
   1.439 +			}
   1.440 +		TUSB_PRINT("Device successfully re-enumerated\n");
   1.441 +
   1.442 +		// Make sure program versions match if testing against USBRFLCT
   1.443 +		if (iRW->MaxBufSize() != 0)
   1.444 +			{
   1.445 +			r = iRW->ExchangeVersions();
   1.446 +			if (r != KErrNone)
   1.447 +				{
   1.448 +				TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
   1.449 +				CActiveScheduler::Stop();
   1.450 +				return;
   1.451 +				}
   1.452 +			}
   1.453 +		}
   1.454 +	else
   1.455 +		{
   1.456 +		// Execute one of the 'proper' program functions
   1.457 +		switch (aChar)
   1.458 +			{
   1.459 +		case 'l':					// start loop test
   1.460 +		case 'L':
   1.461 +			TUSB_PRINT("-> Loop test selected\n");
   1.462 +			iRW->SetTransferMode(ELoop);
   1.463 +			iRW->SendPreamble();
   1.464 +			break;
   1.465 +		case 'c':					// start loop/compare test
   1.466 +		case 'C':
   1.467 +			TUSB_PRINT("-> Loop test with compare selected\n");
   1.468 +			iRW->SetTransferMode(ELoopComp);
   1.469 +			iRW->SendPreamble();
   1.470 +			break;
   1.471 +		case 'r':					// start receive-only test
   1.472 +		case 'R':
   1.473 +			TUSB_PRINT("-> Receive-only test selected\n");
   1.474 +			iRW->SetTransferMode(EReceiveOnly);
   1.475 +			iRW->SendPreamble();
   1.476 +			break;
   1.477 +		case 't':					// start transmit-only test
   1.478 +		case 'T':
   1.479 +			TUSB_PRINT("-> Transmit-only test selected\n");
   1.480 +			iRW->SetTransferMode(ETransmitOnly);
   1.481 +			iRW->SendPreamble();
   1.482 +			break;
   1.483 +		case 'g':					// start transmit & get-from-file test
   1.484 +		case 'G':
   1.485 +			TUSB_PRINT("-> Transmit from file test selected\n");
   1.486 +			iRW->SetTransferMode(ETransmitOnly);
   1.487 +			iRW->ReadFromDisk(ETrue);
   1.488 +			iRW->SendPreamble();
   1.489 +			break;
   1.490 +		case 'p':					// start receive & put-to-file test
   1.491 +		case 'P':
   1.492 +			TUSB_PRINT("-> Receive to file test selected\n");
   1.493 +			iRW->SetTransferMode(EReceiveOnly);
   1.494 +			iRW->WriteToDisk(ETrue);
   1.495 +			iRW->SendPreamble();
   1.496 +			break;
   1.497 +		case 'w':					// remote-wakeup
   1.498 +		case 'W':
   1.499 +			TUSB_PRINT("-> Signal Remote-wakeup selected\n");
   1.500 +			iPort.SignalRemoteWakeup();
   1.501 +			break;
   1.502 +		case 's':					// stop either
   1.503 +		case 'S':
   1.504 +			TUSB_PRINT("-> Stop transfer selected\n");
   1.505 +			iRW->Stop();
   1.506 +			break;
   1.507 +#ifdef WITH_DUMP_OPTION
   1.508 +		case 'd':					// dump controller registers
   1.509 +		case 'D':
   1.510 +			TUSB_PRINT("-> Dump option selected\n");
   1.511 +			iPort.DumpRegisters();
   1.512 +			QueryRxBuffer();
   1.513 +			break;
   1.514 +#endif
   1.515 +		case 'e':					// ReEnumerate()
   1.516 +		case 'E':
   1.517 +			TUSB_PRINT("-> Re-enumerate device selected\n");
   1.518 +			ReEnumerate();
   1.519 +			break;
   1.520 +		case 'q':					// quit
   1.521 +		case 'Q':
   1.522 +			TUSB_PRINT("-> Quit program selected\n");
   1.523 +			TUSB_VERBOSE_PRINT("CActiveConsole: stopping active scheduler...");
   1.524 +			CActiveScheduler::Stop();
   1.525 +			return;
   1.526 +		default:
   1.527 +			TUSB_PRINT1("-> Not a valid input character: %c", aChar.operator TUint());
   1.528 +			goto request_char;
   1.529 +			}
   1.530 +		}
   1.531 + request_char:
   1.532 +	RequestCharacter();
   1.533 +	return;
   1.534 +	}
   1.535 +
   1.536 +
   1.537 +#ifdef WITH_DUMP_OPTION
   1.538 +void CActiveConsole::QueryRxBuffer()
   1.539 +	{
   1.540 +	// Let's look whether there's data in the rx buffer
   1.541 +	TInt bytes = 0;
   1.542 +	TInt r = iPort.QueryReceiveBuffer(EEndpoint2, bytes);
   1.543 +	if (r != KErrNone)
   1.544 +		{
   1.545 +		RDebug::Print(_L(" Error %d on querying read buffer\n"), r);
   1.546 +		}
   1.547 +	else
   1.548 +		{
   1.549 +		RDebug::Print(_L(" %d bytes in RX buffer\n"), bytes);
   1.550 +		}
   1.551 +	}
   1.552 +#endif
   1.553 +
   1.554 +
   1.555 +TInt CActiveConsole::QueryUsbClientL()
   1.556 +	{
   1.557 +	// Not really just querying... but rather setting up the whole interface.
   1.558 +	// It's in fact a bit lengthy, but all these steps are required, once,
   1.559 +	// and in that order.
   1.560 +
   1.561 +	// Get device/endpoint capabilities
   1.562 +	//
   1.563 +	// A TPckg, or TPckBuf was not used in the following, because
   1.564 +	//
   1.565 +	//	 TPckgBuf<TUsbcEndpointData[KUsbcMaxEndpoints]> databuf;
   1.566 +	//
   1.567 +	// doesn't work. Also,
   1.568 +	//
   1.569 +	//	 TUsbcEndpointData data[KUsbcMaxEndpoints];
   1.570 +	//	 TPckgBuf<TUsbcEndpointData[KUsbcMaxEndpoints]> databuf(data);
   1.571 +	//
   1.572 +	// doesn't work. Also,
   1.573 +	//
   1.574 +	//	 TUsbcEndpointData data[KUsbcMaxEndpoints];
   1.575 +	//	 TPckgBuf<TUsbcEndpointData[]> databuf(data);
   1.576 +	//
   1.577 +	// doesn't work.
   1.578 +	// So we seem to have to stick to the ugly cast below.
   1.579 +	//
   1.580 +	//	 TUsbcEndpointData data[KUsbcMaxEndpoints];
   1.581 +	//	 TPtr8 databuf(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   1.582 +	//
   1.583 +
   1.584 +	// Device
   1.585 +	TUsbDeviceCaps d_caps;
   1.586 +	TInt r = iPort.DeviceCaps(d_caps);
   1.587 +	if (r != KErrNone)
   1.588 +		{
   1.589 +		TUSB_PRINT1("Error %d on querying device capabilities", r);
   1.590 +		return KErrGeneral;
   1.591 +		}
   1.592 +	const TInt n = d_caps().iTotalEndpoints;
   1.593 +
   1.594 +	TUSB_PRINT("###  USB device capabilities:");
   1.595 +	TUSB_PRINT1("Number of endpoints:                        %d", n);
   1.596 +	TUSB_PRINT1("Supports Software-Connect:                  %s",
   1.597 +				d_caps().iConnect ? _S("yes") : _S("no"));
   1.598 +	TUSB_PRINT1("Device is Self-Powered:                     %s",
   1.599 +				d_caps().iSelfPowered ? _S("yes") : _S("no"));
   1.600 +	TUSB_PRINT1("Supports Remote-Wakeup:                     %s",
   1.601 +				d_caps().iRemoteWakeup ? _S("yes") : _S("no"));
   1.602 +	TUSB_PRINT1("Supports High-speed:                        %s",
   1.603 +				d_caps().iHighSpeed ? _S("yes") : _S("no"));
   1.604 +	TUSB_PRINT1("Supports OTG:                               %s",
   1.605 +				iOtg ? _S("yes") : _S("no"));
   1.606 +	TUSB_PRINT1("Supports unpowered cable detection:         %s",
   1.607 +				(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ?
   1.608 +				_S("yes") : _S("no"));
   1.609 +	TUSB_PRINT1("Supports endpoint resource alloc scheme V2: %s\n",
   1.610 +				(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ?
   1.611 +				_S("yes") : _S("no"));
   1.612 +	TUSB_PRINT("");
   1.613 +
   1.614 +	iSoftwareConnect = d_caps().iConnect;					// we need to remember this
   1.615 +
   1.616 +	if (n < 2)
   1.617 +		{
   1.618 +		TUSB_PRINT1("Error: only %d endpoints available on device", n);
   1.619 +		return KErrGeneral;
   1.620 +		}
   1.621 +
   1.622 +	// Endpoints
   1.623 +	TUsbcEndpointData data[KUsbcMaxEndpoints];
   1.624 +	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   1.625 +	r = iPort.EndpointCaps(dataptr);
   1.626 +	if (r != KErrNone)
   1.627 +		{
   1.628 +		TUSB_PRINT1("Error %d on querying endpoint capabilities", r);
   1.629 +		return KErrGeneral;
   1.630 +		}
   1.631 +	TUSB_PRINT("### USB device endpoint capabilities:");
   1.632 +	for (TInt i = 0; i < n; i++)
   1.633 +		{
   1.634 +		const TUsbcEndpointCaps* caps = &data[i].iCaps;
   1.635 +		TUSB_PRINT2("Endpoint: SizeMask = 0x%08x TypeDirMask = 0x%08x",
   1.636 +					caps->iSizes, caps->iTypesAndDir);
   1.637 +		}
   1.638 +	TUSB_PRINT("");
   1.639 +
   1.640 +	// Set up the active interface
   1.641 +	TUsbcInterfaceInfoBuf ifc;
   1.642 +	TInt ep_found = 0;
   1.643 +	TBool foundBulkIN = EFalse;
   1.644 +	TBool foundBulkOUT = EFalse;
   1.645 +	for (TInt i = 0; i < n; i++)
   1.646 +		{
   1.647 +		const TUsbcEndpointCaps* const caps = &data[i].iCaps;
   1.648 +		const TInt mps = caps->MaxPacketSize();
   1.649 +		if (!foundBulkIN &&
   1.650 +			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) ==
   1.651 +			(KUsbEpTypeBulk | KUsbEpDirIn))
   1.652 +			{
   1.653 +			if (!(mps == 64 || mps == 512))
   1.654 +				{
   1.655 +				TUSB_PRINT1("Funny Bulk IN MaxPacketSize: %d - T_USB will probably fail...", mps);
   1.656 +				}
   1.657 +			// EEndpoint1 is going to be our Tx (IN) endpoint
   1.658 +			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
   1.659 +			ifc().iEndpointData[0].iDir	 = KUsbEpDirIn;
   1.660 +			ifc().iEndpointData[0].iSize = mps;
   1.661 +			foundBulkIN = ETrue;
   1.662 +			if (++ep_found == 2)
   1.663 +				break;
   1.664 +			}
   1.665 +		else if (!foundBulkOUT &&
   1.666 +			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) ==
   1.667 +			(KUsbEpTypeBulk | KUsbEpDirOut))
   1.668 +			{
   1.669 +			if (!(mps == 64 || mps == 512))
   1.670 +				{
   1.671 +				TUSB_PRINT1("Funny Bulk OUT MaxPacketSize: %d - T_USB will probably fail...", mps);
   1.672 +				}
   1.673 +			// EEndpoint2 is going to be our Rx (OUT) endpoint
   1.674 +			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
   1.675 +			ifc().iEndpointData[1].iDir	 = KUsbEpDirOut;
   1.676 +			ifc().iEndpointData[1].iSize = mps;
   1.677 +			foundBulkOUT = ETrue;
   1.678 +			if (++ep_found == 2)
   1.679 +				break;
   1.680 +			}
   1.681 +		}
   1.682 +	if (ep_found != 2)
   1.683 +		{
   1.684 +		TUSB_PRINT1("No suitable endpoints found", r);
   1.685 +		return KErrGeneral;
   1.686 +		}
   1.687 +
   1.688 +	_LIT16(ifcname, "T_USB Test Interface (Default Setting 0)");
   1.689 +	ifc().iString = const_cast<TDesC16*>(&ifcname);
   1.690 +	ifc().iTotalEndpointsUsed = 2;
   1.691 +	ifc().iClass.iClassNum	  = 0xff;						// vendor-specific
   1.692 +	ifc().iClass.iSubClassNum = 0xff;						// vendor-specific
   1.693 +	ifc().iClass.iProtocolNum = 0xff;						// vendor-specific
   1.694 +	r = iPort.SetInterface(0, ifc, iBandwidthPriority);
   1.695 +	if (r != KErrNone)
   1.696 +		{
   1.697 +		TUSB_PRINT1("Error %d on setting active interface", r);
   1.698 +		}
   1.699 +
   1.700 +	// Find ep's for an alternate ifc setting.
   1.701 +	// We're not really going to use it, but it gives USBCV et al. more stuff to play with.
   1.702 +	if (!SupportsAlternateInterfaces())
   1.703 +		{
   1.704 +		TUSB_PRINT("Alternate Interfaces not supported - skipping alternate setting setup\n");
   1.705 +		return KErrNone;
   1.706 +		}
   1.707 +	ep_found = 0;
   1.708 +	TBool foundIsoIN  = EFalse;
   1.709 +	TBool foundIsoOUT = EFalse;
   1.710 +
   1.711 +	// NB! We cannot assume that any specific device has any given set of
   1.712 +	// capabilities, so whilst we try and set an assortment of endpoint types
   1.713 +	// we may not get what we want.
   1.714 +
   1.715 +	// Also, note that the endpoint[] array in the interface descriptor
   1.716 +	// must be filled from ep[0]...ep[n-1].
   1.717 +
   1.718 +	for (TInt i = 0; i < n; i++)
   1.719 +		{
   1.720 +		const TUsbcEndpointCaps* const caps = &data[i].iCaps;
   1.721 +		const TInt mps = caps->MaxPacketSize();
   1.722 +		if (!foundIsoIN &&
   1.723 +			(caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirIn)) ==
   1.724 +			(KUsbEpTypeIsochronous | KUsbEpDirIn))
   1.725 +			{
   1.726 +			// This is going to be our Iso TX (IN) endpoint
   1.727 +			ifc().iEndpointData[ep_found].iType  = KUsbEpTypeIsochronous;
   1.728 +			ifc().iEndpointData[ep_found].iDir   = KUsbEpDirIn;
   1.729 +			ifc().iEndpointData[ep_found].iSize  = mps;
   1.730 +			ifc().iEndpointData[ep_found].iInterval = 0x01;	// 2^(bInterval-1)ms, bInterval must be [1..16]
   1.731 +			ifc().iEndpointData[ep_found].iInterval_Hs  = 0x01;	// same as for FS
   1.732 +			ifc().iEndpointData[ep_found].iExtra = 2;		// 2 extra bytes for Audio Class EP descriptor
   1.733 +			foundIsoIN = ETrue;
   1.734 +			if (++ep_found == 2)
   1.735 +				break;
   1.736 +			}
   1.737 +		else if (!foundIsoOUT &&
   1.738 +				 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirOut)) ==
   1.739 +				 (KUsbEpTypeIsochronous | KUsbEpDirOut))
   1.740 +			{
   1.741 +			// This is going to be our Iso RX (OUT) endpoint
   1.742 +			ifc().iEndpointData[ep_found].iType  = KUsbEpTypeIsochronous;
   1.743 +			ifc().iEndpointData[ep_found].iDir   = KUsbEpDirOut;
   1.744 +			ifc().iEndpointData[ep_found].iSize  = mps;
   1.745 +			ifc().iEndpointData[ep_found].iInterval = 0x01;	// 2^(bInterval-1)ms, bInterval must be [1..16]
   1.746 +			ifc().iEndpointData[ep_found].iExtra = 2;		// 2 extra bytes for Audio Class EP descriptor
   1.747 +			foundIsoOUT = ETrue;
   1.748 +			if (++ep_found == 2)
   1.749 +				break;
   1.750 +			}
   1.751 +		}
   1.752 +	// Let's try to add Bulk endpoints up to the max # of 2.
   1.753 +	if (ep_found < 2)
   1.754 +		{
   1.755 +		for (TInt i = 0; i < n; i++)
   1.756 +			{
   1.757 +			const TUsbcEndpointCaps* const caps = &data[i].iCaps;
   1.758 +			const TUint mps = caps->MaxPacketSize();
   1.759 +			if (caps->iTypesAndDir & KUsbEpTypeBulk)
   1.760 +				{
   1.761 +				const TUint dir = (caps->iTypesAndDir & KUsbEpDirIn) ? KUsbEpDirIn : KUsbEpDirOut;
   1.762 +				ifc().iEndpointData[ep_found].iType = KUsbEpTypeBulk;
   1.763 +				ifc().iEndpointData[ep_found].iDir = dir;
   1.764 +				ifc().iEndpointData[ep_found].iSize = mps;
   1.765 +				if (++ep_found == 2)
   1.766 +					break;
   1.767 +				}
   1.768 +			}
   1.769 +		}
   1.770 +	if (ep_found == 0)
   1.771 +		{
   1.772 +		TUSB_PRINT("Not enough suitable endpoints found for alt ifc");
   1.773 +		// not a disaster though
   1.774 +		return KErrNone;
   1.775 +		}
   1.776 +
   1.777 +	_LIT16(ifcname1, "T_USB Test Interface (Alternate Setting 1)");
   1.778 +	ifc().iString = const_cast<TDesC16*>(&ifcname1);
   1.779 +	ifc().iTotalEndpointsUsed = ep_found;
   1.780 +	ifc().iClass.iClassNum	  = KUsbAudioInterfaceClassCode;
   1.781 +	ifc().iClass.iSubClassNum = KUsbAudioInterfaceSubclassCode_Audiostreaming;
   1.782 +	ifc().iClass.iProtocolNum = KUsbAudioInterfaceProtocolCode_Pr_Protocol_Undefined;
   1.783 +	// Tell the driver that this setting is not interested in Ep0 requests:
   1.784 +	ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
   1.785 +	r = iPort.SetInterface(1, ifc);
   1.786 +	if (r != KErrNone)
   1.787 +		{
   1.788 +		TUSB_PRINT1("Error %d on setting alternate interface", r);
   1.789 +		}
   1.790 +
   1.791 +	return r;
   1.792 +	}
   1.793 +
   1.794 +
   1.795 +void CActiveConsole::AllocateEndpointDMA(TEndpointNumber aEndpoint)
   1.796 +	{
   1.797 +	TInt r = iPort.AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA);
   1.798 +	if (r == KErrNone)
   1.799 +		RDebug::Print(_L("DMA allocation on endpoint %d: KErrNone"), aEndpoint);
   1.800 +	else if (r == KErrInUse)
   1.801 +		RDebug::Print(_L("DMA allocation on endpoint %d: KErrInUse"), aEndpoint);
   1.802 +	else if (r == KErrNotSupported)
   1.803 +		RDebug::Print(_L("DMA allocation on endpoint %d: KErrNotSupported"), aEndpoint);
   1.804 +	else
   1.805 +		RDebug::Print(_L("DMA allocation on endpoint %d: unexpected return value %d"),
   1.806 +					  aEndpoint, r);
   1.807 +	TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA);
   1.808 +	TUSB_PRINT2("DMA on endpoint %d %s\n",
   1.809 +				aEndpoint, res ? _S("allocated") : _S("not allocated"));
   1.810 +
   1.811 +	if ((r == KErrNone) && !res)
   1.812 +		RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n"));
   1.813 +	else if ((r != KErrNone) && res)
   1.814 +		RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n"));
   1.815 +	}
   1.816 +
   1.817 +
   1.818 +void CActiveConsole::DeAllocateEndpointDMA(TEndpointNumber aEndpoint)
   1.819 +	{
   1.820 +	TInt r = iPort.DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA);
   1.821 +	if (r == KErrNone)
   1.822 +		RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNone"), aEndpoint);
   1.823 +	else if (r == KErrNotSupported)
   1.824 +		RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNotSupported"), aEndpoint);
   1.825 +	else
   1.826 +		RDebug::Print(_L("DMA deallocation on endpoint %d: unexpected return value %d"),
   1.827 +					  aEndpoint, r);
   1.828 +	TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA);
   1.829 +	TUSB_PRINT2("DMA on endpoint %d %s\n",
   1.830 +				aEndpoint, res ? _S("allocated") : _S("not allocated"));
   1.831 +	}
   1.832 +
   1.833 +
   1.834 +void CActiveConsole::AllocateDoubleBuffering(TEndpointNumber aEndpoint)
   1.835 +	{
   1.836 +	TInt r = iPort.AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
   1.837 +	if (r == KErrNone)
   1.838 +		RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNone"), aEndpoint);
   1.839 +	else if (r == KErrInUse)
   1.840 +		RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrInUse"), aEndpoint);
   1.841 +	else if (r == KErrNotSupported)
   1.842 +		RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNotSupported"), aEndpoint);
   1.843 +	else
   1.844 +		RDebug::Print(_L("Double Buffering allocation on endpoint %d: unexpected return value %d"),
   1.845 +					  aEndpoint, r);
   1.846 +	TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
   1.847 +	TUSB_PRINT2("Double Buffering on endpoint %d %s\n",
   1.848 +				aEndpoint, res ? _S("allocated") : _S("not allocated"));
   1.849 +
   1.850 +	if ((r == KErrNone) && !res)
   1.851 +		RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n"));
   1.852 +	else if ((r != KErrNone) && res)
   1.853 +		RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n"));
   1.854 +	}
   1.855 +
   1.856 +
   1.857 +void CActiveConsole::DeAllocateDoubleBuffering(TEndpointNumber aEndpoint)
   1.858 +	{
   1.859 +	TInt r = iPort.DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
   1.860 +	if (r == KErrNone)
   1.861 +		RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNone"), aEndpoint);
   1.862 +	else if (r == KErrNotSupported)
   1.863 +		RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNotSupported"), aEndpoint);
   1.864 +	else
   1.865 +		RDebug::Print(_L("Double Buffering deallocation on endpoint %d: unexpected return value %d"),
   1.866 +					  aEndpoint, r);
   1.867 +	TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
   1.868 +	TUSB_PRINT2("Double Buffering on endpoint %d %s\n",
   1.869 +				aEndpoint, res ? _S("allocated") : _S("not allocated"));
   1.870 +	}
   1.871 +
   1.872 +
   1.873 +TInt CActiveConsole::ReEnumerate()
   1.874 +	{
   1.875 +	TRequestStatus enum_status;
   1.876 +	iPort.ReEnumerate(enum_status);
   1.877 +	if (!iSoftwareConnect)
   1.878 +		{
   1.879 +		iConsole->Printf(_L("This device does not support software\n"));
   1.880 +		iConsole->Printf(_L("disconnect/reconnect\n"));
   1.881 +		iConsole->Printf(_L("Please physically unplug and replug\n"));
   1.882 +		iConsole->Printf(_L("the USB cable NOW... "));
   1.883 +		}
   1.884 +	iConsole->Printf(_L("\n>>> START THE USBRFLCT PROGRAM ON THE HOST SIDE NOW <<<\n"));
   1.885 +	User::WaitForRequest(enum_status);
   1.886 +	if (enum_status != KErrNone)
   1.887 +		{
   1.888 +		TUSB_PRINT1("Error: Re-enumeration status = %d", enum_status.Int());
   1.889 +		return KErrGeneral;
   1.890 +		}
   1.891 +	TUsbcDeviceState device_state =	EUsbcDeviceStateUndefined;
   1.892 +	TInt r = iPort.DeviceStatus(device_state);
   1.893 +	if (r != KErrNone)
   1.894 +		{
   1.895 +		TUSB_PRINT1("Error %d on querying device state", r);
   1.896 +		}
   1.897 +	else
   1.898 +		{
   1.899 +		TUSB_PRINT1("Current device state: %s",
   1.900 +					(device_state == EUsbcDeviceStateUndefined) ? _S("Undefined") :
   1.901 +					((device_state == EUsbcDeviceStateAttached) ? _S("Attached") :
   1.902 +					 ((device_state == EUsbcDeviceStatePowered) ? _S("Powered") :
   1.903 +					  ((device_state == EUsbcDeviceStateDefault) ? _S("Default") :
   1.904 +					   ((device_state == EUsbcDeviceStateAddress) ? _S("Address") :
   1.905 +						((device_state == EUsbcDeviceStateConfigured) ? _S("Configured") :
   1.906 +						 ((device_state == EUsbcDeviceStateSuspended) ? _S("Suspended") :
   1.907 +						  _S("Unknown"))))))));
   1.908 +		}
   1.909 +
   1.910 +	// Check the speed of the established physical USB connection
   1.911 +	iHighSpeed = iPort.CurrentlyUsingHighSpeed();
   1.912 +	if (iHighSpeed)
   1.913 +		{
   1.914 +		TUSB_PRINT("---> USB High-speed Testing\n");
   1.915 +		// It can only be 512 bytes when using high-speed.
   1.916 +		iRW->SetMaxPacketSize(512);							// iRW already exists at this point
   1.917 +		}
   1.918 +	else
   1.919 +		{
   1.920 +		TUSB_PRINT("---> USB Full-speed Testing\n");
   1.921 +		// We only support 64 bytes when using full-speed.
   1.922 +		iRW->SetMaxPacketSize(64);							// iRW already exists at this point
   1.923 +		}
   1.924 +
   1.925 +	return KErrNone;
   1.926 +	}
   1.927 +
   1.928 +
   1.929 +#ifdef test
   1.930 +#undef test
   1.931 +#endif
   1.932 +#define test(x) \
   1.933 +	do { \
   1.934 +		if (!(x)) \
   1.935 +			{ \
   1.936 +			TUSB_PRINT1("Failure occurred!	- on line %d", __LINE__); \
   1.937 +			return KErrGeneral; \
   1.938 +			} \
   1.939 +	} while (0)
   1.940 +
   1.941 +
   1.942 +TInt CActiveConsole::SetupDescriptors()
   1.943 +	{
   1.944 +	// === Device Descriptor
   1.945 +
   1.946 +	TInt deviceDescriptorSize = 0;
   1.947 +	iPort.GetDeviceDescriptorSize(deviceDescriptorSize);
   1.948 +	test(static_cast<TUint>(deviceDescriptorSize) == KUsbDescSize_Device);
   1.949 +
   1.950 +	TBuf8<KUsbDescSize_Device> deviceDescriptor;
   1.951 +	TInt r = iPort.GetDeviceDescriptor(deviceDescriptor);
   1.952 +	test(r == KErrNone);
   1.953 +
   1.954 +	const TInt KUsbSpecOffset = 2;
   1.955 +	const TInt KUsbVendorIdOffset = 8;
   1.956 +	const TInt KUsbProductIdOffset = 10;
   1.957 +	const TInt KUsbDevReleaseOffset = 12;
   1.958 +	// Change the USB spec number to 2.00
   1.959 +	deviceDescriptor[KUsbSpecOffset]   = 0x00;
   1.960 +	deviceDescriptor[KUsbSpecOffset+1] = 0x02;
   1.961 +	// Change the device vendor ID (VID) to 0x0E22 (Symbian)
   1.962 +	deviceDescriptor[KUsbVendorIdOffset]   = 0x22;			// little endian!
   1.963 +	deviceDescriptor[KUsbVendorIdOffset+1] = 0x0E;
   1.964 +	// Change the device product ID (PID) to 0x1111
   1.965 +	deviceDescriptor[KUsbProductIdOffset]	= 0x11;
   1.966 +	deviceDescriptor[KUsbProductIdOffset+1] = 0x11;
   1.967 +	// Change the device release number to 3.05
   1.968 +	deviceDescriptor[KUsbDevReleaseOffset]	 = 0x05;
   1.969 +	deviceDescriptor[KUsbDevReleaseOffset+1] = 0x03;
   1.970 +	r = iPort.SetDeviceDescriptor(deviceDescriptor);
   1.971 +	test(r == KErrNone);
   1.972 +
   1.973 +	const TUint16 Vid = (((TUint16)deviceDescriptor[KUsbVendorIdOffset + 1] << 8) & 0xff00) |
   1.974 +		deviceDescriptor[KUsbVendorIdOffset];
   1.975 +	const TUint16 Pid = (((TUint16)deviceDescriptor[KUsbProductIdOffset + 1] << 8) & 0xff00) |
   1.976 +		deviceDescriptor[KUsbProductIdOffset];
   1.977 +
   1.978 +	TUSB_PRINT6("\nVID = 0x%04X / PID = 0x%04X / DevRel = %d%d.%d%d\n", Vid, Pid,
   1.979 +				((deviceDescriptor[KUsbDevReleaseOffset + 1] >> 4) & 0x0f),
   1.980 +				(deviceDescriptor[KUsbDevReleaseOffset + 1] & 0x0f),
   1.981 +				((deviceDescriptor[KUsbDevReleaseOffset] >> 4) & 0x0f),
   1.982 +				(deviceDescriptor[KUsbDevReleaseOffset] & 0x0f));
   1.983 +
   1.984 +	// === Configuration Descriptor
   1.985 +
   1.986 +	TInt configDescriptorSize = 0;
   1.987 +	iPort.GetConfigurationDescriptorSize(configDescriptorSize);
   1.988 +	test(static_cast<TUint>(configDescriptorSize) == KUsbDescSize_Config);
   1.989 +
   1.990 +	TBuf8<KUsbDescSize_Config> configDescriptor;
   1.991 +	r = iPort.GetConfigurationDescriptor(configDescriptor);
   1.992 +	test(r == KErrNone);
   1.993 +
   1.994 +	// Change the reported max power to 100mA (= 2 * 0x32),
   1.995 +	// which is the highest value allowed for a bus-powered device.
   1.996 +	const TInt KUsbMaxPowerOffset = 8;
   1.997 +	configDescriptor[KUsbMaxPowerOffset] = 0x32;
   1.998 +	r = iPort.SetConfigurationDescriptor(configDescriptor);
   1.999 +	test(r == KErrNone);
  1.1000 +
  1.1001 +	// === String Descriptors
  1.1002 +
  1.1003 +	// Set up two arbitrary string descriptors, which can be queried
  1.1004 +	// manually from the host side for testing purposes (for instance
  1.1005 +	// using 'usbcheck').
  1.1006 +
  1.1007 +	_LIT16(string_one, "Arbitrary String Descriptor Test String 1");
  1.1008 +	TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(string_one);
  1.1009 +	r = iPort.SetStringDescriptor(stridx1, wr_str);
  1.1010 +	test(r == KErrNone);
  1.1011 +
  1.1012 +	_LIT16(string_two, "Another Arbitrary String Descriptor Test String");
  1.1013 +	wr_str.FillZ(wr_str.MaxLength());
  1.1014 +	wr_str = string_two;
  1.1015 +	r = iPort.SetStringDescriptor(stridx2, wr_str);
  1.1016 +	test(r == KErrNone);
  1.1017 +
  1.1018 +	return KErrNone;
  1.1019 +	}
  1.1020 +
  1.1021 +
  1.1022 +//
  1.1023 +// --- class CActiveRW ---------------------------------------------------------
  1.1024 +//
  1.1025 +
  1.1026 +CActiveRW::CActiveRW(CConsoleBase* aConsole, RDevUsbcClient* aPort, TBool aVerboseOutput)
  1.1027 +	: CActive(EPriorityNormal),
  1.1028 +	  iConsole(aConsole),
  1.1029 +	  iPort(aPort),
  1.1030 +	  iBufSz(KInitialBufSz),
  1.1031 +	  iMaxBufSz(KInitialBufSz),
  1.1032 +	  iMaxPktSz(0),
  1.1033 +	  iCurrentXfer(ENone),
  1.1034 +	  iXferMode(::ENone),
  1.1035 +	  iDoStop(EFalse),
  1.1036 +	  iPktNum(~0),
  1.1037 +	  iVerbose(aVerboseOutput)
  1.1038 +	{
  1.1039 +	TUSB_VERBOSE_PRINT("CActiveRW::CActiveRW()");
  1.1040 +	}
  1.1041 +
  1.1042 +
  1.1043 +CActiveRW* CActiveRW::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort, TBool aVerboseOutput)
  1.1044 +	{
  1.1045 +	CActiveRW* self = new (ELeave) CActiveRW(aConsole, aPort, aVerboseOutput);
  1.1046 +	CleanupStack::PushL(self);
  1.1047 +	self->ConstructL();
  1.1048 +	CActiveScheduler::Add(self);
  1.1049 +	CleanupStack::Pop();									// self
  1.1050 +	return self;
  1.1051 +	}
  1.1052 +
  1.1053 +
  1.1054 +void CActiveRW::ConstructL()
  1.1055 +	{
  1.1056 +	TUSB_VERBOSE_PRINT("CActiveRW::ConstructL()");
  1.1057 +
  1.1058 +	User::LeaveIfError(iFs.Connect());
  1.1059 +
  1.1060 +	// Prepare Preamble buffer
  1.1061 +	iPreambleBuf.SetMax();
  1.1062 +	iPreambleBuf.FillZ();
  1.1063 +
  1.1064 +	// Prepare IN data buffer
  1.1065 +	iWriteBuf.SetMax();
  1.1066 +	for (TInt i = 0; i < iWriteBuf.MaxSize(); i++)
  1.1067 +		{
  1.1068 +		iWriteBuf[i] = i;
  1.1069 +		}
  1.1070 +
  1.1071 +	// Prepare OUT data buffer
  1.1072 +	iReadBuf.SetMax();
  1.1073 +
  1.1074 +	// Create read timeout timer active object (but don't activate it yet)
  1.1075 +	iTimeoutTimer = CActiveTimer::NewL(iConsole, iPort, iVerbose);
  1.1076 +	if (!iTimeoutTimer)
  1.1077 +		{
  1.1078 +		TUSB_PRINT("Failed to create timeout timer");
  1.1079 +		}
  1.1080 +	}
  1.1081 +
  1.1082 +
  1.1083 +CActiveRW::~CActiveRW()
  1.1084 +	{
  1.1085 +	TUSB_VERBOSE_PRINT("CActiveRW::~CActiveRW()");
  1.1086 +	Cancel();												// base class
  1.1087 +	delete iTimeoutTimer;
  1.1088 +	iFile.Close();
  1.1089 +	iFs.Close();
  1.1090 +	}
  1.1091 +
  1.1092 +
  1.1093 +void CActiveRW::SetMaxBufSize(TInt aBufSz)
  1.1094 +	{
  1.1095 +	if (aBufSz > KMaxBufSize)
  1.1096 +		{
  1.1097 +		TUSB_PRINT2("SetMaxBufSize(): too large: %d! (using %d)", aBufSz, KMaxBufSize);
  1.1098 +		aBufSz = KMaxBufSize;
  1.1099 +		}
  1.1100 +	iMaxBufSz = aBufSz;
  1.1101 +	}
  1.1102 +
  1.1103 +
  1.1104 +void CActiveRW::SetMaxPacketSize(TInt aPktSz)
  1.1105 +	{
  1.1106 +	iMaxPktSz = aPktSz;
  1.1107 +	}
  1.1108 +
  1.1109 +
  1.1110 +TInt CActiveRW::MaxBufSize() const
  1.1111 +	{
  1.1112 +	return iMaxBufSz;
  1.1113 +	}
  1.1114 +
  1.1115 +
  1.1116 +void CActiveRW::SetTransferMode(TXferMode aMode)
  1.1117 +	{
  1.1118 +	iXferMode = aMode;
  1.1119 +	if (aMode == EReceiveOnly || aMode == ETransmitOnly)
  1.1120 +		{
  1.1121 +		// For streaming transfers we do this only once.
  1.1122 +		iBufSz = iMaxBufSz;
  1.1123 +		}
  1.1124 +	}
  1.1125 +
  1.1126 +
  1.1127 +void CActiveRW::RunL()
  1.1128 +	{
  1.1129 +	TUSB_VERBOSE_PRINT("CActiveRW::RunL()");
  1.1130 +	if (iStatus != KErrNone)
  1.1131 +		{
  1.1132 +		TUSB_PRINT1("Error %d in RunL", iStatus.Int());
  1.1133 +		}
  1.1134 +	if (iDoStop)
  1.1135 +		{
  1.1136 +		TUSB_PRINT("Stopped");
  1.1137 +		iDoStop = EFalse;
  1.1138 +		return;
  1.1139 +		}
  1.1140 +	switch (iCurrentXfer)
  1.1141 +		{
  1.1142 +	case EPreamble:
  1.1143 +		if (iXferMode != EReceiveOnly)
  1.1144 +			SendData();										// next we write data
  1.1145 +		else
  1.1146 +			ReadData();										// or we read data
  1.1147 +		break;
  1.1148 +	case EWriteXfer:
  1.1149 +		if (iXferMode == ETransmitOnly)
  1.1150 +			SendData();										// next we send data
  1.1151 +		else
  1.1152 +			ReadData();										// or we read data
  1.1153 +		break;
  1.1154 +	case EReadXfer:
  1.1155 +		if (iXferMode == EReceiveOnly)
  1.1156 +			{
  1.1157 +			const TUint32 num = *reinterpret_cast<const TUint32*>(iReadBuf.Ptr());
  1.1158 +			if (num != ++iPktNum)
  1.1159 +				{
  1.1160 +				TUSB_PRINT2("*** rcv'd wrong pkt number: 0x%x (expected: 0x%x)", num, iPktNum);
  1.1161 +				// Update the packet number with the received number, so that
  1.1162 +				// if a single packet is duplicated or lost then a single error occurs
  1.1163 +				iPktNum = num;
  1.1164 +				}
  1.1165 +			if (iDiskAccessEnabled)
  1.1166 +				{
  1.1167 +				// Write out to disk previous completed Read
  1.1168 +				TUSB_VERBOSE_PRINT2("iMaxBufSz = %d (iReadBuf.Size(): %d)",
  1.1169 +									iMaxBufSz, iReadBuf.Size());
  1.1170 +				WriteBufferToDisk(iReadBuf, iMaxBufSz);
  1.1171 +				}
  1.1172 +			ReadData();										// next we read data
  1.1173 +			break;
  1.1174 +			}
  1.1175 +		if (iXferMode == ELoopComp)
  1.1176 +			{
  1.1177 +			if (!CompareBuffers(iBufSz))
  1.1178 +				{
  1.1179 +				TUSB_PRINT1("Error while comparing tx & rx buffers for packet 0x%x", iPktNum);
  1.1180 +				}
  1.1181 +			}
  1.1182 +		else if (iBufSz > 3)
  1.1183 +			{
  1.1184 +			const TUint32 num = *reinterpret_cast<const TUint32*>(iReadBuf.Ptr());
  1.1185 +			if (num != iPktNum)
  1.1186 +				{
  1.1187 +				TUSB_PRINT2("*** rcv'd wrong pkt number: 0x%x (expected: 0x%x)", num, iPktNum);
  1.1188 +				}
  1.1189 +			}
  1.1190 +		if (iBufSz == iMaxBufSz)
  1.1191 +			{
  1.1192 +			iBufSz = KInitialBufSz;
  1.1193 +			}
  1.1194 +		else
  1.1195 +			{
  1.1196 +			++iBufSz;
  1.1197 +			}
  1.1198 +		SendPreamble();										// next we send the length
  1.1199 +		break;
  1.1200 +	default:
  1.1201 +		TUSB_PRINT("Oops. (Shouldn't end up here...)");
  1.1202 +		break;
  1.1203 +		}
  1.1204 +	return;
  1.1205 +	}
  1.1206 +
  1.1207 +
  1.1208 +TInt CActiveRW::SendVersion()
  1.1209 +	{
  1.1210 +	TUSB_VERBOSE_PRINT("CActiveRW::SendVersion()");
  1.1211 +	if (iXferMode != ::ENone)
  1.1212 +		{
  1.1213 +		TUSB_PRINT1("Error : wrong state: %d", iXferMode);
  1.1214 +		return KErrGeneral;
  1.1215 +		}
  1.1216 +	// Here we send our version packet to the host.
  1.1217 +	// (We can use the preamble buffer because we only need it
  1.1218 +	//  once and that's also before the preamble uses.)
  1.1219 +	TUSB_PRINT1("Sending T_USB version: %d\n", KTusbVersion);
  1.1220 +	iPreambleBuf.FillZ();
  1.1221 +	*reinterpret_cast<TUint32*>(&iPreambleBuf[0]) = SWAP_BYTES_32(KTusbVersion);
  1.1222 +	// A 'magic' string so that USBRFLCT doesn't interpret the first 4 bytes
  1.1223 +	// of a data preamble packet of an old T_USB as the version number.
  1.1224 +	iPreambleBuf[4] = 'V';
  1.1225 +	iPreambleBuf[5] = 'e';
  1.1226 +	iPreambleBuf[6] = 'r';
  1.1227 +	iPreambleBuf[7] = 's';
  1.1228 +	TRequestStatus send_status;
  1.1229 +	iPort->Write(send_status, EEndpoint1, iPreambleBuf, KPreambleLength);
  1.1230 +	TUSB_VERBOSE_PRINT("Waiting for write request to complete...");
  1.1231 +	User::WaitForRequest(send_status);
  1.1232 +	TUSB_VERBOSE_PRINT("...done.\n");
  1.1233 +	return send_status.Int();
  1.1234 +	}
  1.1235 +
  1.1236 +
  1.1237 +TInt CActiveRW::ReceiveVersion()
  1.1238 +	{
  1.1239 +	TUSB_VERBOSE_PRINT("CActiveRW::ReceiveVersion()");
  1.1240 +	if (iXferMode != ::ENone)
  1.1241 +		{
  1.1242 +		TUSB_PRINT1("Error : wrong state: %d", iXferMode);
  1.1243 +		return KErrGeneral;
  1.1244 +		}
  1.1245 +	// Here we try to receive a version packet from the host.
  1.1246 +	// (We can use the preamble buffer because we only need it
  1.1247 +	//  once and that's also before the preamble uses.)
  1.1248 +	TUSB_PRINT("Getting host program versions...");
  1.1249 +	iPreambleBuf.FillZ();
  1.1250 +	TRequestStatus receive_status;
  1.1251 +	iPort->Read(receive_status, EEndpoint2, iPreambleBuf, KPreambleLength);
  1.1252 +	TUSB_VERBOSE_PRINT("Waiting for read request to complete...");
  1.1253 +	iTimeoutTimer->Activate(5000000);						// Host gets 5s
  1.1254 +	User::WaitForRequest(receive_status, iTimeoutTimer->iStatus);
  1.1255 +	if (receive_status == KRequestPending)
  1.1256 +		{
  1.1257 +		// Read() still pending...
  1.1258 +		TUSB_PRINT("Cancelling USB Read(): no response from host.\n");
  1.1259 +		iPort->ReadCancel(EEndpoint2);
  1.1260 +		TUSB_PRINT("THIS COULD BE DUE TO AN OLD VERSION OF USBRFLCT ON THE PC:");
  1.1261 +		TUSB_PRINT3("PLEASE CHECK THE VERSION THERE - WE NEED AT LEAST V%d.%d.%d!\n",
  1.1262 +					KUsbrflctVersionMajor, KUsbrflctVersionMinor, KUsbrflctVersionMicro);
  1.1263 +		TUSB_PRINT("When updating an existing USBRFLCT installation <= v1.3.1,\n" \
  1.1264 +				   L"the following three things will need to be done:\n");
  1.1265 +		TUSB_PRINT("1. Connect the device to the PC & start T_USB (just as now),\n" \
  1.1266 +				   L"then find the USB device in the Windows Device Manager\n" \
  1.1267 +				   L"('Control Panel'->'System'->'Hardware'->'Device Manager').\n" \
  1.1268 +				   L"Right click on the device name and choose 'Uninstall...'.\n");
  1.1269 +		TUSB_PRINT("2. In c:\\winnt\\inf\\, find (by searching for \"Symbian\") and\n" \
  1.1270 +				   L"delete the *.INF file that was used to install the existing\n" \
  1.1271 +				   L"version of USBRFLCT.SYS. Make sure to also delete the\n" \
  1.1272 +				   L"precompiled version of that file (<samename>.PNF).\n");
  1.1273 +		TUSB_PRINT("3. In c:\\winnt\\system32\\drivers\\, delete the file USBRFLCT.SYS.\n");
  1.1274 +		TUSB_PRINT("Then unplug & reconnect the USB device and, when prompted, install\n" \
  1.1275 +				   L"the new USBRFLCT.SYS driver using the .INF file from this distribution.\n" \
  1.1276 +				   L"(All files can be found under e32test\\win32\\usbrflct_distribution\\.)\n");
  1.1277 +		TUSB_PRINT("Use the new USBRFLCT.EXE from this distribution.\n");
  1.1278 +		}
  1.1279 +	else
  1.1280 +		{
  1.1281 +		TUSB_VERBOSE_PRINT("...done.");
  1.1282 +		// Timeout not needed any longer
  1.1283 +		TUSB_VERBOSE_PRINT("Cancelling timeout timer: USB Read() completed.\n");
  1.1284 +		iTimeoutTimer->Cancel();
  1.1285 +		}
  1.1286 +	return receive_status.Int();
  1.1287 +	}
  1.1288 +
  1.1289 +
  1.1290 +TInt CActiveRW::ExchangeVersions()
  1.1291 +	{
  1.1292 +	TUSB_VERBOSE_PRINT("CActiveRW::ExchangeVersions()");
  1.1293 +	// First check the version of USBRFLCT that's running on the host
  1.1294 +	TInt r = ReceiveVersion();
  1.1295 +	if (r != KErrNone)
  1.1296 +		{
  1.1297 +		return KErrGeneral;
  1.1298 +		}
  1.1299 +	TUint8 usbrflct_ver_major = iPreambleBuf[0];
  1.1300 +	TUint8 usbrflct_ver_minor = iPreambleBuf[1];
  1.1301 +	TUint8 usbrflct_ver_micro = iPreambleBuf[2];
  1.1302 +	TUint8 usbio_ver_major = iPreambleBuf[3];
  1.1303 +	TUint8 usbio_ver_minor = iPreambleBuf[4];
  1.1304 +	TUSB_PRINT5("Host-side: USBRFLCT v%d.%d.%d  USBIO v%d.%d\n",
  1.1305 +				usbrflct_ver_major, usbrflct_ver_minor, usbrflct_ver_micro,
  1.1306 +				usbio_ver_major, usbio_ver_minor);
  1.1307 +	if (usbrflct_ver_major < KUsbrflctVersionMajor)
  1.1308 +		{
  1.1309 +		TUSB_PRINT1("USBRFLCT version not sufficient (need at least v%d.x.x)\n",
  1.1310 +					KUsbrflctVersionMajor);
  1.1311 +		return KErrGeneral;
  1.1312 +		}
  1.1313 +	// Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without
  1.1314 +	// GCC compiler warning because Kxxx can also be zero (in which case there's no '<').
  1.1315 +	else if ((usbrflct_ver_minor <= KUsbrflctVersionMinor) &&
  1.1316 +			 !(usbrflct_ver_minor == KUsbrflctVersionMinor))
  1.1317 +		{
  1.1318 +		TUSB_PRINT2("USBRFLCT version not sufficient (need at least v%d.%d.x)\n",
  1.1319 +					KUsbrflctVersionMajor, KUsbrflctVersionMinor);
  1.1320 +		return KErrGeneral;
  1.1321 +		}
  1.1322 +	// Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without
  1.1323 +	// GCC compiler warning because Kxxx can also be zero (in which case there's no '<').
  1.1324 +	else if ((usbrflct_ver_micro <= KUsbrflctVersionMicro) &&
  1.1325 +			 !(usbrflct_ver_micro == KUsbrflctVersionMicro))
  1.1326 +		{
  1.1327 +		TUSB_PRINT3("USBRFLCT version not sufficient (need at least v%d.%d.%d)\n",
  1.1328 +					KUsbrflctVersionMajor, KUsbrflctVersionMinor, KUsbrflctVersionMicro);
  1.1329 +		return KErrGeneral;
  1.1330 +		}
  1.1331 +	// Now we send T_USB's version to the host
  1.1332 +	r = SendVersion();
  1.1333 +	if (r != KErrNone)
  1.1334 +		{
  1.1335 +		return KErrGeneral;
  1.1336 +		}
  1.1337 +	return KErrNone;
  1.1338 +	}
  1.1339 +
  1.1340 +
  1.1341 +void CActiveRW::SendPreamble()
  1.1342 +	{
  1.1343 +	TUSB_VERBOSE_PRINT("CActiveRW::SendPreamble()");
  1.1344 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1345 +	TUSB_VERBOSE_PRINT1("Sending data length: %d bytes", iBufSz);
  1.1346 +	*reinterpret_cast<TUint32*>(&iPreambleBuf[0]) = SWAP_BYTES_32(iBufSz);
  1.1347 +	iPort->Write(iStatus, EEndpoint1, iPreambleBuf, KPreambleLength);
  1.1348 +	iCurrentXfer = EPreamble;
  1.1349 +	SetActive();
  1.1350 +	}
  1.1351 +
  1.1352 +
  1.1353 +void CActiveRW::SendData()
  1.1354 +	{
  1.1355 +	TUSB_VERBOSE_PRINT("CActiveRW::SendData()");
  1.1356 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1357 +	if (iDiskAccessEnabled)
  1.1358 +		{
  1.1359 +		ReadBufferFromDisk(iWriteBuf, iBufSz);
  1.1360 +		}
  1.1361 +	++iPktNum;
  1.1362 +	if (iBufSz > 3)
  1.1363 +		{
  1.1364 +		*reinterpret_cast<TUint32*>(const_cast<TUint8*>(iWriteBuf.Ptr())) = iPktNum;
  1.1365 +		}
  1.1366 +	if (iXferMode == ELoopComp)
  1.1367 +		{
  1.1368 +		for (TInt i = 4; i < iBufSz; i++)
  1.1369 +			{
  1.1370 +			iWriteBuf[i] = static_cast<TUint8>(iPktNum & 0x000000ff);
  1.1371 +			}
  1.1372 +		}
  1.1373 +	TUSB_VERBOSE_PRINT1("Sending data: %d bytes", iBufSz);
  1.1374 +	iPort->Write(iStatus, EEndpoint1, iWriteBuf, iBufSz);
  1.1375 +	iCurrentXfer = EWriteXfer;
  1.1376 +	SetActive();
  1.1377 +	}
  1.1378 +
  1.1379 +
  1.1380 +TInt CActiveRW::SelectDrive()
  1.1381 +	{
  1.1382 +	TDriveList driveList;
  1.1383 +	TInt r = iFs.DriveList(driveList);
  1.1384 +	if (r != KErrNone)
  1.1385 +		{
  1.1386 +		TUSB_PRINT1("RFs::DriveList() returned %d", r);
  1.1387 +		return r;
  1.1388 +		}
  1.1389 +	TUSB_PRINT("Available drives:");
  1.1390 +	for (TInt n = 0; n < KMaxDrives; n++)
  1.1391 +		{
  1.1392 +		if (driveList[n] != 0)
  1.1393 +			{
  1.1394 +			TVolumeInfo volumeInfo;
  1.1395 +			r = iFs.Volume(volumeInfo, n);
  1.1396 +			if (r == KErrNone)
  1.1397 +				{
  1.1398 +				TPtr name(volumeInfo.iName.Des());
  1.1399 +				TUSB_PRINT2("Drive %c: %- 16S", 'A' + n, &name);
  1.1400 +				if (volumeInfo.iDrive.iMediaAtt & KMediaAttWriteProtected)
  1.1401 +					TUSB_PRINT("  (read-only)");
  1.1402 +				TUSB_PRINT("");
  1.1403 +				}
  1.1404 +			}
  1.1405 +		}
  1.1406 +	iConsole->Printf(_L("Please select a drive letter (or 'Q' to quit)..."));
  1.1407 +	TChar driveLetter;
  1.1408 +	TInt driveNumber;
  1.1409 +	TVolumeInfo volumeInfo;
  1.1410 +	do
  1.1411 +		{
  1.1412 +		driveLetter = (TUint)iConsole->Getch();
  1.1413 +		driveLetter.UpperCase();
  1.1414 +		if (driveLetter == 'Q')
  1.1415 +			{
  1.1416 +			return KErrCancel;
  1.1417 +			}
  1.1418 +		driveNumber = (TUint)driveLetter - 'A';
  1.1419 +		r = iFs.Volume(volumeInfo, driveNumber);
  1.1420 +		}
  1.1421 +	while ((driveNumber < 0) ||
  1.1422 +		   (driveNumber >= KMaxDrives) ||
  1.1423 +		   (r) ||
  1.1424 +		   (driveList[driveNumber] == 0) ||
  1.1425 +		   (volumeInfo.iDrive.iMediaAtt & KMediaAttWriteProtected));
  1.1426 +
  1.1427 +	iFileName.Format(_L("%c:"), driveLetter.operator TUint());
  1.1428 +	iFileName.Append(KFileName);
  1.1429 +	TUSB_PRINT1("\nFilename = %S", &iFileName);
  1.1430 +	TUSB_PRINT1("File size: %d", KMaxFileSize);
  1.1431 +	return r;
  1.1432 +	}
  1.1433 +
  1.1434 +
  1.1435 +TInt CActiveRW::WriteToDisk(TBool aEnable)
  1.1436 +	{
  1.1437 +	iDiskAccessEnabled = aEnable;
  1.1438 +	TInt r = KErrNone;
  1.1439 +
  1.1440 +	if (iDiskAccessEnabled)
  1.1441 +		{
  1.1442 +		r = SelectDrive();
  1.1443 +		if (r != KErrNone)
  1.1444 +			{
  1.1445 +			iDiskAccessEnabled = EFalse;
  1.1446 +			return r;
  1.1447 +			}
  1.1448 +		// open the record file
  1.1449 +		r = iFile.Replace(iFs, iFileName, EFileWrite);
  1.1450 +		iFileOffset = 0;
  1.1451 +		}
  1.1452 +	return r;
  1.1453 +	}
  1.1454 +
  1.1455 +
  1.1456 +TInt CActiveRW::ReadFromDisk(TBool aEnable)
  1.1457 +	{
  1.1458 +	iDiskAccessEnabled = aEnable;
  1.1459 +	TInt r = KErrNone;
  1.1460 +
  1.1461 +	if (iDiskAccessEnabled)
  1.1462 +		{
  1.1463 +		r = SelectDrive();
  1.1464 +		if (r != KErrNone)
  1.1465 +			{
  1.1466 +			iDiskAccessEnabled = EFalse;
  1.1467 +			return r;
  1.1468 +			}
  1.1469 +		// First create the file & fill it
  1.1470 +		r = iFile.Replace(iFs, iFileName, EFileWrite);
  1.1471 +		if (r != KErrNone)
  1.1472 +			{
  1.1473 +			TUSB_PRINT1("RFile::Replace() returned %d", r);
  1.1474 +			iDiskAccessEnabled = EFalse;
  1.1475 +			return r;
  1.1476 +			}
  1.1477 +		const TInt KBufferSize = 4 * 1024;
  1.1478 +		TBuf8<KBufferSize> buffer;
  1.1479 +		buffer.SetLength(KBufferSize);
  1.1480 +		for (TInt n = 0; n < KBufferSize; n++)
  1.1481 +			{
  1.1482 +			buffer[n] = static_cast<TUint8>(n & 0x000000ff);
  1.1483 +			}
  1.1484 +		TUSB_PRINT("Writing data to file (this may take some minutes...)");
  1.1485 +		for (TInt n = 0; n < KMaxFileSize; n += KBufferSize)
  1.1486 +			{
  1.1487 +			r = iFile.Write(buffer, KBufferSize);
  1.1488 +			if (r != KErrNone)
  1.1489 +				{
  1.1490 +				TUSB_PRINT1("RFile::Write() returned %d (disk full?)", r);
  1.1491 +				iFile.Close();
  1.1492 +				iDiskAccessEnabled = EFalse;
  1.1493 +				return r;
  1.1494 +				}
  1.1495 +			}
  1.1496 +		TUSB_PRINT("Done.");
  1.1497 +		iFile.Close();
  1.1498 +		// Now open the file for reading
  1.1499 +		r = iFile.Open(iFs, iFileName, EFileRead);
  1.1500 +		if (r != KErrNone)
  1.1501 +			{
  1.1502 +			TUSB_PRINT1("RFile::Open() returned %d", r);
  1.1503 +			iDiskAccessEnabled = EFalse;
  1.1504 +			return r;
  1.1505 +			}
  1.1506 +		iFileOffset = 0;
  1.1507 +		}
  1.1508 +	return r;
  1.1509 +	}
  1.1510 +
  1.1511 +
  1.1512 +void CActiveRW::WriteBufferToDisk(TDes8& aBuffer, TInt aLen)
  1.1513 +	{
  1.1514 +	TUSB_VERBOSE_PRINT1("CActiveRW::WriteBufferToDisk(), len = %d", aLen);
  1.1515 +	TInt r = iFile.Write(aBuffer, aLen);
  1.1516 +	if (r != KErrNone)
  1.1517 +		{
  1.1518 +		TUSB_PRINT2("Error writing to %S (%d)", &iFileName, r);
  1.1519 +		iDiskAccessEnabled = EFalse;
  1.1520 +		return;
  1.1521 +		}
  1.1522 +	iFileOffset += aLen;
  1.1523 +	if (iFileOffset >= KMaxFileSize)
  1.1524 +		{
  1.1525 +		iFileOffset = 0;
  1.1526 +		iFile.Seek(ESeekStart, iFileOffset);
  1.1527 +		}
  1.1528 +	}
  1.1529 +
  1.1530 +
  1.1531 +void CActiveRW::ReadBufferFromDisk(TDes8& aBuffer, TInt aLen)
  1.1532 +	{
  1.1533 +	if (iFileOffset + aLen >= KMaxFileSize)
  1.1534 +		{
  1.1535 +		iFileOffset = 0;
  1.1536 +		iFile.Seek(ESeekStart, iFileOffset);
  1.1537 +		}
  1.1538 +	const TInt r = iFile.Read(aBuffer, aLen);
  1.1539 +	if (r != KErrNone)
  1.1540 +		{
  1.1541 +		TUSB_PRINT2("Error reading from %S (%d)", &iFileName, r);
  1.1542 +		iDiskAccessEnabled = EFalse;
  1.1543 +		return;
  1.1544 +		}
  1.1545 +	TInt readLen = aBuffer.Length();
  1.1546 +	TUSB_VERBOSE_PRINT1("CActiveRW::ReadBufferFromDisk(), len = %d\n", readLen);
  1.1547 +	if (readLen < aLen)
  1.1548 +		{
  1.1549 +		TUSB_PRINT3("Only %d bytes of %d read from file %S)",
  1.1550 +					readLen, aLen, &iFileName);
  1.1551 +		iDiskAccessEnabled = EFalse;
  1.1552 +		return;
  1.1553 +		}
  1.1554 +	iFileOffset += aLen;
  1.1555 +	}
  1.1556 +
  1.1557 +
  1.1558 +void CActiveRW::ReadData()
  1.1559 +	{
  1.1560 +	TUSB_VERBOSE_PRINT("CActiveRW::ReadData()");
  1.1561 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1562 +	TUSB_VERBOSE_PRINT1("Reading data: %d bytes", iBufSz);
  1.1563 +	if (iXferMode == EReceiveOnly)
  1.1564 +		{
  1.1565 +		TUSB_VERBOSE_PRINT("  (rx only)");
  1.1566 +		iPort->Read(iStatus, EEndpoint2, iReadBuf, iBufSz);
  1.1567 +		}
  1.1568 +	else if (iBufSz == iMaxPktSz)
  1.1569 +		{
  1.1570 +		// we also want to test the packet version of Read()
  1.1571 +		TUSB_VERBOSE_PRINT("  (a single packet)");
  1.1572 +		iPort->ReadPacket(iStatus, EEndpoint2, iReadBuf, iBufSz);
  1.1573 +		}
  1.1574 +	else if (iBufSz == iReadBuf.MaxSize())
  1.1575 +		{
  1.1576 +		// or we could perhaps test the three-parameter version
  1.1577 +		TUSB_VERBOSE_PRINT("  (w/o length)");
  1.1578 +		iPort->Read(iStatus, EEndpoint2, iReadBuf);
  1.1579 +		}
  1.1580 +	else
  1.1581 +		{
  1.1582 +		// otherwise, we use the universal default version
  1.1583 +		TUSB_VERBOSE_PRINT("  (normal)");
  1.1584 +		iPort->Read(iStatus, EEndpoint2, iReadBuf, iBufSz);
  1.1585 +		}
  1.1586 +	iCurrentXfer = EReadXfer;
  1.1587 +	SetActive();
  1.1588 +	}
  1.1589 +
  1.1590 +
  1.1591 +void CActiveRW::Stop()
  1.1592 +	{
  1.1593 +	if (!IsActive())
  1.1594 +		{
  1.1595 +		TUSB_PRINT("CActiveRW::Stop(): Not active");
  1.1596 +		return;
  1.1597 +		}
  1.1598 +	TUSB_PRINT("Cancelling outstanding transfer requests\n");
  1.1599 +	iBufSz = KInitialBufSz;
  1.1600 +	iPktNum = ~0;
  1.1601 +	iDoStop = ETrue;
  1.1602 +	iCurrentXfer = ENone;
  1.1603 +	Cancel();
  1.1604 +	}
  1.1605 +
  1.1606 +
  1.1607 +void CActiveRW::DoCancel()
  1.1608 +	{
  1.1609 +	TUSB_VERBOSE_PRINT("CActiveRW::DoCancel()");
  1.1610 +	// Canceling the transfer requests can be done explicitly
  1.1611 +	// for every transfer...
  1.1612 +	iPort->WriteCancel(EEndpoint1);
  1.1613 +	iPort->ReadCancel(EEndpoint2);
  1.1614 +	// or like this:
  1.1615 +	iPort->EndpointTransferCancel(~0);
  1.1616 +	}
  1.1617 +
  1.1618 +
  1.1619 +TBool CActiveRW::CompareBuffers(TInt aLen)
  1.1620 +	{
  1.1621 +	TUSB_VERBOSE_PRINT1("CActiveRW::CompareBuffers(%d)", aLen);
  1.1622 +	for (TInt i = 0; i < aLen; i++)
  1.1623 +		{
  1.1624 +		if (iReadBuf[i] != iWriteBuf[i])
  1.1625 +			{
  1.1626 +			TUSB_VERBOSE_PRINT1("Error: for i = %d:", i);
  1.1627 +			TUSB_VERBOSE_PRINT2("iReadBuf: %d != iWriteBuf: %d",
  1.1628 +								iReadBuf[i], iWriteBuf[i]);
  1.1629 +			return EFalse;
  1.1630 +			}
  1.1631 +		}
  1.1632 +	return ETrue;
  1.1633 +	}
  1.1634 +
  1.1635 +
  1.1636 +//
  1.1637 +// --- class CActiveStallNotifier ---------------------------------------------------------
  1.1638 +//
  1.1639 +
  1.1640 +CActiveStallNotifier::CActiveStallNotifier(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1641 +										   TBool aVerboseOutput)
  1.1642 +	: CActive(EPriorityNormal),
  1.1643 +	  iConsole(aConsole),
  1.1644 +	  iPort(aPort),
  1.1645 +	  iEndpointState(0),
  1.1646 +	  iVerbose(aVerboseOutput)
  1.1647 +	{
  1.1648 +	CActiveScheduler::Add(this);
  1.1649 +	}
  1.1650 +
  1.1651 +CActiveStallNotifier* CActiveStallNotifier::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1652 +												 TBool aVerboseOutput)
  1.1653 +	{
  1.1654 +	CActiveStallNotifier* self = new (ELeave) CActiveStallNotifier(aConsole, aPort, aVerboseOutput);
  1.1655 +	CleanupStack::PushL(self);
  1.1656 +	self->ConstructL();
  1.1657 +	CleanupStack::Pop();									// self
  1.1658 +	return self;
  1.1659 +	}
  1.1660 +
  1.1661 +
  1.1662 +void CActiveStallNotifier::ConstructL()
  1.1663 +	{}
  1.1664 +
  1.1665 +
  1.1666 +CActiveStallNotifier::~CActiveStallNotifier()
  1.1667 +	{
  1.1668 +	TUSB_VERBOSE_PRINT("CActiveStallNotifier::~CActiveStallNotifier()");
  1.1669 +	Cancel();												// base class
  1.1670 +	}
  1.1671 +
  1.1672 +
  1.1673 +void CActiveStallNotifier::DoCancel()
  1.1674 +	{
  1.1675 +	TUSB_VERBOSE_PRINT("CActiveStallNotifier::DoCancel()");
  1.1676 +	iPort->EndpointStatusNotifyCancel();
  1.1677 +	}
  1.1678 +
  1.1679 +
  1.1680 +void CActiveStallNotifier::RunL()
  1.1681 +	{
  1.1682 +	// This just displays the bitmap, showing which endpoints (if any) are now stalled.
  1.1683 +	// In a real world program, the user could take here appropriate action (cancel a
  1.1684 +	// transfer request or whatever).
  1.1685 +	TUSB_VERBOSE_PRINT1("StallNotifier: Endpointstate 0x%x\n", iEndpointState);
  1.1686 +	Activate();
  1.1687 +	}
  1.1688 +
  1.1689 +
  1.1690 +void CActiveStallNotifier::Activate()
  1.1691 +	{
  1.1692 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1693 +	iPort->EndpointStatusNotify(iStatus, iEndpointState);
  1.1694 +	SetActive();
  1.1695 +	}
  1.1696 +
  1.1697 +
  1.1698 +//
  1.1699 +// --- class CActiveDeviceStateNotifier ---------------------------------------------------------
  1.1700 +//
  1.1701 +
  1.1702 +CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1703 +													   TBool aVerboseOutput)
  1.1704 +	: CActive(EPriorityNormal),
  1.1705 +	  iConsole(aConsole),
  1.1706 +	  iPort(aPort),
  1.1707 +	  iDeviceState(0),
  1.1708 +	  iVerbose(aVerboseOutput)
  1.1709 +	{
  1.1710 +	CActiveScheduler::Add(this);
  1.1711 +	}
  1.1712 +
  1.1713 +CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1714 +															 TBool aVerboseOutput)
  1.1715 +	{
  1.1716 +	CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aConsole, aPort, aVerboseOutput);
  1.1717 +	CleanupStack::PushL(self);
  1.1718 +	self->ConstructL();
  1.1719 +	CleanupStack::Pop();									// self
  1.1720 +	return self;
  1.1721 +	}
  1.1722 +
  1.1723 +
  1.1724 +void CActiveDeviceStateNotifier::ConstructL()
  1.1725 +	{}
  1.1726 +
  1.1727 +
  1.1728 +CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()
  1.1729 +	{
  1.1730 +	TUSB_VERBOSE_PRINT("CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()");
  1.1731 +	Cancel();												// base class
  1.1732 +	}
  1.1733 +
  1.1734 +
  1.1735 +void CActiveDeviceStateNotifier::DoCancel()
  1.1736 +	{
  1.1737 +	TUSB_VERBOSE_PRINT("CActiveDeviceStateNotifier::DoCancel()");
  1.1738 +	iPort->AlternateDeviceStatusNotifyCancel();
  1.1739 +	}
  1.1740 +
  1.1741 +
  1.1742 +void CActiveDeviceStateNotifier::RunL()
  1.1743 +	{
  1.1744 +	// This displays the device state.
  1.1745 +	// In a real world program, the user could take here appropriate action (cancel a
  1.1746 +	// transfer request or whatever).
  1.1747 +	if (!(iDeviceState & KUsbAlternateSetting) && iVerbose)
  1.1748 +		{
  1.1749 +		switch (iDeviceState)
  1.1750 +			{
  1.1751 +		case EUsbcDeviceStateUndefined:
  1.1752 +			TUSB_PRINT("Device State notifier: Undefined");
  1.1753 +			break;
  1.1754 +		case EUsbcDeviceStateAttached:
  1.1755 +			TUSB_PRINT("Device State notifier: Attached");
  1.1756 +			break;
  1.1757 +		case EUsbcDeviceStatePowered:
  1.1758 +			TUSB_PRINT("Device State notifier: Powered");
  1.1759 +			break;
  1.1760 +		case EUsbcDeviceStateDefault:
  1.1761 +			TUSB_PRINT("Device State notifier: Default");
  1.1762 +			break;
  1.1763 +		case EUsbcDeviceStateAddress:
  1.1764 +			TUSB_PRINT("Device State notifier: Address");
  1.1765 +			break;
  1.1766 +		case EUsbcDeviceStateConfigured:
  1.1767 +			TUSB_PRINT("Device State notifier: Configured");
  1.1768 +			break;
  1.1769 +		case EUsbcDeviceStateSuspended:
  1.1770 +			TUSB_PRINT("Device State notifier: Suspended");
  1.1771 +			break;
  1.1772 +		default:
  1.1773 +			TUSB_PRINT("Device State notifier: ***BAD***");
  1.1774 +			}
  1.1775 +		}
  1.1776 +	else if (iDeviceState & KUsbAlternateSetting)
  1.1777 +		{
  1.1778 +		TUSB_PRINT1("Device State notifier: Alternate interface setting has changed: now %d",
  1.1779 +					iDeviceState & ~KUsbAlternateSetting);
  1.1780 +		}
  1.1781 +	Activate();
  1.1782 +	}
  1.1783 +
  1.1784 +
  1.1785 +void CActiveDeviceStateNotifier::Activate()
  1.1786 +	{
  1.1787 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1788 +	iPort->AlternateDeviceStatusNotify(iStatus, iDeviceState);
  1.1789 +	SetActive();
  1.1790 +	}
  1.1791 +
  1.1792 +
  1.1793 +//
  1.1794 +// --- class CActiveTimer ---------------------------------------------------------
  1.1795 +//
  1.1796 +
  1.1797 +CActiveTimer::CActiveTimer(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1798 +						   TBool aVerboseOutput)
  1.1799 +	: CActive(EPriorityNormal),
  1.1800 +	  iConsole(aConsole),
  1.1801 +	  iPort(aPort),
  1.1802 +	  iVerbose(aVerboseOutput)
  1.1803 +	{
  1.1804 +	CActiveScheduler::Add(this);
  1.1805 +	}
  1.1806 +
  1.1807 +
  1.1808 +CActiveTimer* CActiveTimer::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
  1.1809 +								 TBool aVerboseOutput)
  1.1810 +	{
  1.1811 +	CActiveTimer* self = new (ELeave) CActiveTimer(aConsole, aPort, aVerboseOutput);
  1.1812 +	CleanupStack::PushL(self);
  1.1813 +	self->ConstructL();
  1.1814 +	CleanupStack::Pop();									// self
  1.1815 +	return self;
  1.1816 +	}
  1.1817 +
  1.1818 +
  1.1819 +void CActiveTimer::ConstructL()
  1.1820 +	{
  1.1821 +	User::LeaveIfError(iTimer.CreateLocal());
  1.1822 +	}
  1.1823 +
  1.1824 +
  1.1825 +CActiveTimer::~CActiveTimer()
  1.1826 +	{
  1.1827 +	TUSB_VERBOSE_PRINT("CActiveTimer::~CActiveTimer()");
  1.1828 +	Cancel();												// base class
  1.1829 +	iTimer.Close();
  1.1830 +	}
  1.1831 +
  1.1832 +
  1.1833 +void CActiveTimer::DoCancel()
  1.1834 +	{
  1.1835 +	TUSB_VERBOSE_PRINT("CActiveTimer::DoCancel()");
  1.1836 +	iTimer.Cancel();
  1.1837 +	}
  1.1838 +
  1.1839 +
  1.1840 +void CActiveTimer::RunL()
  1.1841 +	{
  1.1842 +	TUSB_VERBOSE_PRINT("CActiveTimer::RunL()");
  1.1843 +	// Nothing to do here, as we call ReadCancel() after a manual WaitForRequest()
  1.1844 +	// (in CActiveRW::ReceiveVersion()).
  1.1845 +	}
  1.1846 +
  1.1847 +
  1.1848 +void CActiveTimer::Activate(TTimeIntervalMicroSeconds32 aDelay)
  1.1849 +	{
  1.1850 +	__ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
  1.1851 +	iTimer.After(iStatus, aDelay);
  1.1852 +	SetActive();
  1.1853 +	}
  1.1854 +
  1.1855 +
  1.1856 +// -eof-