os/kernelhwsrv/kerneltest/e32test/device/t_usbapi.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test/device/t_usbapi.cpp
sl@0
    15
// Overview:
sl@0
    16
// USB API Test Program (a standalone USB test program).
sl@0
    17
// API Information:
sl@0
    18
// Details:
sl@0
    19
// - Query whether the platform is operating HS (or it is connected to a HS host) or not,
sl@0
    20
// and executes the appropiate tests in each case (see RunTests() for the actual code,
sl@0
    21
// state machine enclosed for clarity):
sl@0
    22
// - Load and open an EUSBC device driver (logical device)
sl@0
    23
// - Setup the USB interface: query device capabilities, setup interface.
sl@0
    24
// - Test allocating DMA and double buffering resources with
sl@0
    25
// AllocateEndpointResource results in their use being correctly reported by
sl@0
    26
// QueryEndpointResourceUse
sl@0
    27
// - Test descriptor manipulation: validate the device, configuration,
sl@0
    28
// interface, alternate interface, endpoint and string descriptor
sl@0
    29
// manipulation.
sl@0
    30
// HS: device_qualifier and other_speed_configuation descriptors.
sl@0
    31
// - Check and validate the EndpointZeroMaxPacketSizes.
sl@0
    32
// - Quick test that calling the following APIs doesn't generate errors: device
sl@0
    33
// control, AlternateDeviceStatusNotify, EndpointStatusNotify
sl@0
    34
// - Test HaltEndpoint and ClearHaltEndpoint correctly result in endpoint
sl@0
    35
// status being reported as stalled/not stalled.
sl@0
    36
// - Test OTG extensions: OTG descriptor manipulations; set/get OTG feature
sl@0
    37
// - Close and free the logical device.
sl@0
    38
// Platforms/Drives/Compatibility:
sl@0
    39
// All.
sl@0
    40
// Assumptions/Requirement/Pre-requisites:
sl@0
    41
// Failures and causes:
sl@0
    42
// Base Port information:
sl@0
    43
// 
sl@0
    44
//
sl@0
    45
sl@0
    46
sl@0
    47
#include <e32test.h>
sl@0
    48
#include <e32debug.h>
sl@0
    49
#include <hal.h>
sl@0
    50
#include <d32usbc.h>
sl@0
    51
#include <d32otgdi.h>
sl@0
    52
sl@0
    53
#include "t_usblib.h"
sl@0
    54
sl@0
    55
sl@0
    56
// --- Local Top Level Variables
sl@0
    57
sl@0
    58
static RTest test(_L("T_USBAPI"));
sl@0
    59
static RDevUsbcClient gPort;
sl@0
    60
static RUsbOtgDriver gOTG;
sl@0
    61
static TBool gSupportsOtg;
sl@0
    62
static TBool gSupportsHighSpeed;
sl@0
    63
static TBool gUsingHighSpeed;
sl@0
    64
static TBool gSoak;
sl@0
    65
static TChar gKeychar = 'a';
sl@0
    66
sl@0
    67
// Store the actual endpoint number(s) of our alternate interface
sl@0
    68
static TInt INT_IN_ep = -1;
sl@0
    69
sl@0
    70
_LIT(KUsbLddFilename, "eusbc");
sl@0
    71
_LIT(KOtgdiLddFilename, "otgdi");
sl@0
    72
_LIT(KUsbDeviceName, "Usbc");
sl@0
    73
sl@0
    74
sl@0
    75
// --- Local Constants
sl@0
    76
sl@0
    77
static const TInt KUsbDesc_SizeOffset = 0;
sl@0
    78
static const TInt KUsbDesc_TypeOffset = 1;
sl@0
    79
sl@0
    80
static const TInt KDevDesc_SpecOffset = 2;
sl@0
    81
static const TInt KDevDesc_DevClassOffset = 4;
sl@0
    82
static const TInt KDevDesc_DevSubClassOffset = 5;
sl@0
    83
static const TInt KDevDesc_DevProtocolOffset = 6;
sl@0
    84
static const TInt KDevDesc_Ep0SizeOffset = 7;
sl@0
    85
static const TInt KDevDesc_VendorIdOffset = 8;
sl@0
    86
static const TInt KDevDesc_ProductIdOffset = 10;
sl@0
    87
static const TInt KDevDesc_DevReleaseOffset = 12;
sl@0
    88
sl@0
    89
static const TInt KConfDesc_AttribOffset = 7;
sl@0
    90
static const TInt KConfDesc_MaxPowerOffset = 8;
sl@0
    91
sl@0
    92
static const TInt KIfcDesc_SettingOffset = 2;
sl@0
    93
static const TInt KIfcDesc_ProtocolOffset = 7;
sl@0
    94
sl@0
    95
static const TInt KEpDesc_PacketSizeOffset = 4;
sl@0
    96
static const TInt KEpDesc_IntervalOffset = 6;
sl@0
    97
static const TInt KEpDesc_SynchAddressOffset = 8;
sl@0
    98
sl@0
    99
sl@0
   100
//
sl@0
   101
// Helper.
sl@0
   102
//
sl@0
   103
static TEndpointState QueryEndpointState(TEndpointNumber aEndpoint)
sl@0
   104
	{
sl@0
   105
	TEndpointState ep_state = EEndpointStateUnknown;
sl@0
   106
	TInt r = gPort.EndpointStatus(aEndpoint, ep_state);
sl@0
   107
	test(r == KErrNone);
sl@0
   108
	test.Printf(_L("Endpoint %d state: %s\n"), aEndpoint,
sl@0
   109
				(ep_state == EEndpointStateNotStalled) ? _S("Not stalled") :
sl@0
   110
				((ep_state == EEndpointStateStalled) ? _S("Stalled") :
sl@0
   111
				 _S("Unknown...")));
sl@0
   112
	return ep_state;
sl@0
   113
	}
sl@0
   114
sl@0
   115
sl@0
   116
// --- Class CActiveKeypressNotifier
sl@0
   117
sl@0
   118
class CActiveKeypressNotifier : public CActive
sl@0
   119
	{
sl@0
   120
public:
sl@0
   121
	static CActiveKeypressNotifier* NewL(CConsoleBase* aConsole);
sl@0
   122
	~CActiveKeypressNotifier();
sl@0
   123
	void RequestCharacter();
sl@0
   124
	void ProcessKeyPressL(TChar aChar);
sl@0
   125
private:
sl@0
   126
	virtual void DoCancel();
sl@0
   127
	virtual void RunL();
sl@0
   128
	CActiveKeypressNotifier(CConsoleBase* aConsole);
sl@0
   129
	void ConstructL() {};
sl@0
   130
private:
sl@0
   131
	CConsoleBase* iConsole;
sl@0
   132
	};
sl@0
   133
sl@0
   134
sl@0
   135
CActiveKeypressNotifier* CActiveKeypressNotifier::NewL(CConsoleBase* aConsole)
sl@0
   136
	{
sl@0
   137
	CActiveKeypressNotifier* self = new (ELeave) CActiveKeypressNotifier(aConsole);
sl@0
   138
	CleanupStack::PushL(self);
sl@0
   139
	self->ConstructL();
sl@0
   140
	CActiveScheduler::Add(self);
sl@0
   141
	CleanupStack::Pop();
sl@0
   142
	return self;
sl@0
   143
	}
sl@0
   144
sl@0
   145
sl@0
   146
CActiveKeypressNotifier::CActiveKeypressNotifier(CConsoleBase* aConsole)
sl@0
   147
	: CActive(EPriorityNormal), iConsole(aConsole)
sl@0
   148
	{}
sl@0
   149
sl@0
   150
sl@0
   151
CActiveKeypressNotifier::~CActiveKeypressNotifier()
sl@0
   152
	{
sl@0
   153
	Cancel();												// base class cancel -> calls our DoCancel
sl@0
   154
	}
sl@0
   155
sl@0
   156
sl@0
   157
void CActiveKeypressNotifier::RunL()
sl@0
   158
	{
sl@0
   159
	gKeychar = (static_cast<TChar>(iConsole->KeyCode()));
sl@0
   160
	RequestCharacter();
sl@0
   161
	}
sl@0
   162
sl@0
   163
sl@0
   164
void CActiveKeypressNotifier::DoCancel()
sl@0
   165
	{
sl@0
   166
	iConsole->ReadCancel();
sl@0
   167
	}
sl@0
   168
sl@0
   169
sl@0
   170
void CActiveKeypressNotifier::RequestCharacter()
sl@0
   171
	{
sl@0
   172
	// A request is issued to the CConsoleBase to accept a character from the keyboard.
sl@0
   173
	if (IsActive())
sl@0
   174
		{
sl@0
   175
		return;
sl@0
   176
		}
sl@0
   177
	iConsole->Read(iStatus);
sl@0
   178
	SetActive();
sl@0
   179
	}
sl@0
   180
sl@0
   181
sl@0
   182
// --- Actual Test Functions
sl@0
   183
sl@0
   184
// 2nd Thread helper function
sl@0
   185
static TInt TestThreadFunction(TAny* aPtr)
sl@0
   186
	{
sl@0
   187
	RThread* other = static_cast<RThread*>(aPtr);
sl@0
   188
	RDevUsbcClient port = gPort;
sl@0
   189
	// Now try to duplicate the USB channel handle
sl@0
   190
	TInt r = port.Duplicate(*other);
sl@0
   191
 	// Wait for 1 second
sl@0
   192
 	User::After(1000000);
sl@0
   193
	return r;
sl@0
   194
	}
sl@0
   195
sl@0
   196
sl@0
   197
static void OpenChannel()
sl@0
   198
	{
sl@0
   199
	test.Start(_L("Open Channel"));
sl@0
   200
sl@0
   201
	test.Next(_L("Load USB LDD"));
sl@0
   202
	TInt r = User::LoadLogicalDevice(KUsbLddFilename);
sl@0
   203
	test(r == KErrNone || r == KErrAlreadyExists);
sl@0
   204
sl@0
   205
	RDevUsbcClient port1;
sl@0
   206
	test.Next(_L("Open local USB channel 1"));
sl@0
   207
	r = port1.Open(0);
sl@0
   208
	test(r == KErrNone);
sl@0
   209
sl@0
   210
	test.Next(_L("Open global USB channel"));
sl@0
   211
	r = gPort.Open(0);
sl@0
   212
	test(r == KErrNone);
sl@0
   213
sl@0
   214
	RDevUsbcClient port2;
sl@0
   215
	test.Next(_L("Open local USB channel 2"));
sl@0
   216
	r = port2.Open(0);
sl@0
   217
	test(r == KErrNone);
sl@0
   218
sl@0
   219
	test.Next(_L("Close USB channel 1"));
sl@0
   220
	port1.Close();
sl@0
   221
sl@0
   222
	RDevUsbcClient port3;
sl@0
   223
	test.Next(_L("Open local USB channel 3"));
sl@0
   224
	r = port3.Open(0);
sl@0
   225
	test(r == KErrNone);
sl@0
   226
sl@0
   227
	test.Next(_L("Close USB channel 2"));
sl@0
   228
	port2.Close();
sl@0
   229
sl@0
   230
	test.Next(_L("Close USB channel 3"));
sl@0
   231
	port3.Close();
sl@0
   232
sl@0
   233
	// Check for OTG support
sl@0
   234
	TBuf8<KUsbDescSize_Otg> otg_desc;
sl@0
   235
	r = gPort.GetOtgDescriptor(otg_desc);
sl@0
   236
	test(r == KErrNotSupported || r == KErrNone);
sl@0
   237
	gSupportsOtg = (r != KErrNotSupported) ? ETrue : EFalse;
sl@0
   238
sl@0
   239
	// On an OTG device we have to start the OTG driver, otherwise the Client
sl@0
   240
	// stack will remain disabled forever.
sl@0
   241
	if (gSupportsOtg)
sl@0
   242
		{
sl@0
   243
		test.Printf(_L("Running on OTG device: loading OTG driver\n"));
sl@0
   244
		test.Next(_L("Load OTG LDD"));
sl@0
   245
		r = User::LoadLogicalDevice(KOtgdiLddFilename);
sl@0
   246
		test((r == KErrNone) || (r == KErrAlreadyExists));
sl@0
   247
sl@0
   248
		test.Next(_L("Open OTG channel"));
sl@0
   249
		r = gOTG.Open();
sl@0
   250
		test(r == KErrNone);
sl@0
   251
sl@0
   252
		test.Next(_L("Start OTG stack"));
sl@0
   253
		r = gOTG.StartStacks();
sl@0
   254
		test(r == KErrNone);
sl@0
   255
		}
sl@0
   256
sl@0
   257
	// Try duplicating channel handle in a second thread
sl@0
   258
	// (which should not work because we don't support it)
sl@0
   259
sl@0
   260
	test.Next(_L("Create 2nd Thread"));
sl@0
   261
	RThread me;
sl@0
   262
 	TThreadId me_id = me.Id();
sl@0
   263
	// We need to open the RThread object, otherwise we'll only get the
sl@0
   264
	// 'special' handle 0xFFFF8001.
sl@0
   265
	test(me.Open(me_id) == KErrNone);
sl@0
   266
	RThread test_thread;
sl@0
   267
	TBuf<17> name = _L("tusbapitestthread");
sl@0
   268
	test(test_thread.Create(name, TestThreadFunction, 0x1000, NULL, &me) == KErrNone);
sl@0
   269
	test.Next(_L("Logon to 2nd Thread"));
sl@0
   270
	TRequestStatus stat;
sl@0
   271
	test_thread.Logon(stat);
sl@0
   272
	test(stat == KRequestPending);
sl@0
   273
	test_thread.Resume();
sl@0
   274
	test.Next(_L("Wait for 2nd Thread to exit"));
sl@0
   275
	User::WaitForRequest(stat);
sl@0
   276
	// Check correct return value of RDevUsbcClient::Duplicate()
sl@0
   277
	test(stat == KErrAccessDenied);
sl@0
   278
	test.Next(_L("Close 2nd Thread"));
sl@0
   279
	test_thread.Close();
sl@0
   280
sl@0
   281
	test.End();
sl@0
   282
	}
sl@0
   283
sl@0
   284
sl@0
   285
static void TestResourceAllocation()
sl@0
   286
	{
sl@0
   287
	test.Start(_L("Test Endpoint Resource Allocation"));
sl@0
   288
sl@0
   289
	test.Next(_L("Request DMA resource"));
sl@0
   290
	const TInt dma = gPort.AllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDMA);
sl@0
   291
	TBool res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDMA);
sl@0
   292
	test.Printf(_L("DMA on endpoint 1 %s\n"),
sl@0
   293
				res ? _S("now allocated") : _S("not allocated"));
sl@0
   294
	if (dma == KErrNone)
sl@0
   295
		// Only if DMA resource was successfully allocated should we expect truth here:
sl@0
   296
		test(res);
sl@0
   297
	else
sl@0
   298
		test(!res);
sl@0
   299
sl@0
   300
	test.Next(_L("Request Double Buffering resource"));
sl@0
   301
	const TInt db = gPort.AllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
sl@0
   302
	res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
sl@0
   303
	test.Printf(_L("Double Buffering on endpoint 1 %s\n"),
sl@0
   304
				res ? _S("now allocated") : _S("not allocated"));
sl@0
   305
	if (db == KErrNone)
sl@0
   306
		// Only if DB resource was successfully allocated should we expect truth here:
sl@0
   307
		test(res);
sl@0
   308
	else
sl@0
   309
		test(!res);
sl@0
   310
sl@0
   311
	test.Next(_L("Deallocate Double Buffering resource"));
sl@0
   312
	TInt r = gPort.DeAllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
sl@0
   313
	// Whether DB is dynamic or permanent - deallocation (if supported) should always return success:
sl@0
   314
	if (db == KErrNone)
sl@0
   315
		test(r == KErrNone);
sl@0
   316
	else
sl@0
   317
		test(r != KErrNone);
sl@0
   318
	res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
sl@0
   319
	test.Printf(_L("Double Buffering on endpoint 1 %s\n"),
sl@0
   320
				res ? _S("still allocated") : _S("not (longer) allocated"));
sl@0
   321
sl@0
   322
	test.Next(_L("Deallocate DMA resource"));
sl@0
   323
	r = gPort.DeAllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDMA);
sl@0
   324
	// Whether DMA is dynamic or permanent - deallocation (if supported) should always return success:
sl@0
   325
	if (dma == KErrNone)
sl@0
   326
		test(r == KErrNone);
sl@0
   327
	else
sl@0
   328
		test(r != KErrNone);
sl@0
   329
	res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDMA);
sl@0
   330
	test.Printf(_L("DMA on endpoint 1 %s\n"),
sl@0
   331
				res ? _S("still allocated") : _S("not (longer) allocated"));
sl@0
   332
sl@0
   333
	test.End();
sl@0
   334
	}
sl@0
   335
sl@0
   336
sl@0
   337
static void SetupInterface()
sl@0
   338
	{
sl@0
   339
	test.Start(_L("Query USB device caps and set up interface"));
sl@0
   340
sl@0
   341
	// Device caps
sl@0
   342
	test.Next(_L("Query USB device caps"));
sl@0
   343
	TUsbDeviceCaps d_caps;
sl@0
   344
	TInt r = gPort.DeviceCaps(d_caps);
sl@0
   345
	test(r == KErrNone);
sl@0
   346
	TInt n = d_caps().iTotalEndpoints;
sl@0
   347
sl@0
   348
	// Global variable - we'll need this value later
sl@0
   349
	gSupportsHighSpeed = d_caps().iHighSpeed;
sl@0
   350
sl@0
   351
	test.Printf(_L("### USB device capabilities:\n"));
sl@0
   352
	test.Printf(_L("Number of endpoints:                        %d\n"), n);
sl@0
   353
	test.Printf(_L("Supports Software-Connect:                  %s\n"),
sl@0
   354
				d_caps().iConnect ? _S("yes") : _S("no"));
sl@0
   355
	test.Printf(_L("Device is Self-Powered:                     %s\n"),
sl@0
   356
				d_caps().iSelfPowered ? _S("yes") : _S("no"));
sl@0
   357
	test.Printf(_L("Supports Remote-Wakeup:                     %s\n"),
sl@0
   358
				d_caps().iRemoteWakeup ? _S("yes") : _S("no"));
sl@0
   359
	test.Printf(_L("Supports High-speed:                        %s\n"),
sl@0
   360
				gSupportsHighSpeed ? _S("yes") : _S("no"));
sl@0
   361
	test.Printf(_L("Supports OTG:                               %s\n"),
sl@0
   362
				gSupportsOtg ? _S("yes") : _S("no"));
sl@0
   363
	test.Printf(_L("Supports unpowered cable detection:         %s\n"),
sl@0
   364
				(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ?
sl@0
   365
				_S("yes") : _S("no"));
sl@0
   366
	test.Printf(_L("Supports endpoint resource alloc scheme V2: %s\n"),
sl@0
   367
				(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ?
sl@0
   368
				_S("yes") : _S("no"));
sl@0
   369
sl@0
   370
	test(n >= 2);
sl@0
   371
	test.Printf(_L("(Device has sufficient endpoints.)\n"));
sl@0
   372
sl@0
   373
	// Endpoint caps
sl@0
   374
	test.Next(_L("Query USB endpoint caps"));
sl@0
   375
	TUsbcEndpointData data[KUsbcMaxEndpoints];
sl@0
   376
	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
sl@0
   377
	r = gPort.EndpointCaps(dataptr);
sl@0
   378
	test(r == KErrNone);
sl@0
   379
sl@0
   380
	test.Printf(_L("### USB device endpoint capabilities:\n"));
sl@0
   381
	for (TInt i = 0; i < n; i++)
sl@0
   382
		{
sl@0
   383
		const TUsbcEndpointCaps* caps = &data[i].iCaps;
sl@0
   384
		test.Printf(_L("Endpoint: SizeMask = 0x%08x TypeDirMask = 0x%08x\n"),
sl@0
   385
					caps->iSizes, caps->iTypesAndDir);
sl@0
   386
		if (caps->iHighBandwidth)
sl@0
   387
			{
sl@0
   388
			test.Printf(_L("  (high-speed, high bandwidth endpoint)\n"));
sl@0
   389
			// Must be HS Int or Iso ep
sl@0
   390
			test(gSupportsHighSpeed);
sl@0
   391
			test(caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpTypeInterrupt));
sl@0
   392
			}
sl@0
   393
		}
sl@0
   394
sl@0
   395
	test.Next(_L("Looking for suitable endpoints"));
sl@0
   396
	// Set the active interface
sl@0
   397
	TUsbcInterfaceInfoBuf ifc;
sl@0
   398
	TInt ep_found = 0;
sl@0
   399
	TBool foundBulkIN = EFalse;
sl@0
   400
	TBool foundBulkOUT = EFalse;
sl@0
   401
	for (TInt i = 0; i < n; i++)
sl@0
   402
		{
sl@0
   403
		const TUsbcEndpointCaps* caps = &data[i].iCaps;
sl@0
   404
		const TInt mps = caps->MaxPacketSize();
sl@0
   405
		if (!foundBulkIN &&
sl@0
   406
			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) ==
sl@0
   407
			(KUsbEpTypeBulk | KUsbEpDirIn))
sl@0
   408
			{
sl@0
   409
			// EEndpoint1 is going to be our TX (IN, write) endpoint
sl@0
   410
			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
sl@0
   411
			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
sl@0
   412
			ifc().iEndpointData[0].iSize = mps;
sl@0
   413
			foundBulkIN = ETrue;
sl@0
   414
			if (++ep_found == 2)
sl@0
   415
				break;
sl@0
   416
			}
sl@0
   417
		else if (!foundBulkOUT &&
sl@0
   418
			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) ==
sl@0
   419
				 (KUsbEpTypeBulk | KUsbEpDirOut))
sl@0
   420
			{
sl@0
   421
			// EEndpoint2 is going to be our RX (OUT, read) endpoint
sl@0
   422
			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
sl@0
   423
			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
sl@0
   424
			ifc().iEndpointData[1].iSize = mps;
sl@0
   425
			foundBulkOUT = ETrue;
sl@0
   426
			if (++ep_found == 2)
sl@0
   427
				break;
sl@0
   428
			}
sl@0
   429
		}
sl@0
   430
	test(ep_found == 2);
sl@0
   431
sl@0
   432
	test.Next(_L("Setting up main interface"));
sl@0
   433
	_LIT16(string, "T_USBAPI Test Interface (Setting 0)");
sl@0
   434
	ifc().iString = const_cast<TDesC16*>(&string);
sl@0
   435
	ifc().iTotalEndpointsUsed = 2;
sl@0
   436
	ifc().iClass.iClassNum	  = 0xff;
sl@0
   437
	ifc().iClass.iSubClassNum = 0xff;
sl@0
   438
	ifc().iClass.iProtocolNum = 0xff;
sl@0
   439
	// Set up the interface.
sl@0
   440
	r = gPort.SetInterface(0, ifc);
sl@0
   441
	test(r == KErrNone);
sl@0
   442
sl@0
   443
	TInt ifc_no = -1;
sl@0
   444
	r = gPort.GetAlternateSetting(ifc_no);
sl@0
   445
	test(r == KErrUsbDeviceNotConfigured);
sl@0
   446
sl@0
   447
	// Some UDCs won't allow endpoint resource manipulation once the hardware has been
sl@0
   448
	// configured and turned on. So we do it here & now:
sl@0
   449
	TestResourceAllocation();
sl@0
   450
sl@0
   451
	// On the other hand, since some UDCs won't let us test many features which require
sl@0
   452
	// register access until the USB hardware is powered up (and because it might start
sl@0
   453
	// out unpowered), we should turn it on here explicitly.
sl@0
   454
	// (It will be turned off automatically by the PIL after all tests have been run,
sl@0
   455
	// when the interface gets deleted.)
sl@0
   456
	test.Next(_L("Powering up UDC (1)"));
sl@0
   457
	r = gPort.PowerUpUdc();
sl@0
   458
	if (!gSupportsOtg)
sl@0
   459
		{
sl@0
   460
		test(r == KErrNone);
sl@0
   461
		}
sl@0
   462
	else
sl@0
   463
		{
sl@0
   464
		test((r == KErrNone) || (r == KErrNotReady));
sl@0
   465
		}
sl@0
   466
	if (gSupportsOtg && (r == KErrNotReady))
sl@0
   467
		{
sl@0
   468
		test.Printf(_L("OTG device but not connected to Host, stopping subtest here.\n"));
sl@0
   469
		test.End();
sl@0
   470
		return;
sl@0
   471
		}
sl@0
   472
	// The board might be attached to a PC with HS controller, thus enabling us
sl@0
   473
	// to test some HS-specific features. For that to work we have to connect
sl@0
   474
	// the board to the PC. The "Found new device" box that may pop up on the PC
sl@0
   475
	// in response to this can be ignored (i.e. just closed).
sl@0
   476
	test.Next(_L("Connecting to Host (1)"));
sl@0
   477
	r = gPort.DeviceConnectToHost();
sl@0
   478
	test(r == KErrNone);
sl@0
   479
 	// Suspend thread to let things get stable on the bus.
sl@0
   480
	test.Printf(_L("Waiting a short moment..."));
sl@0
   481
	User::After(2000000);
sl@0
   482
	test.Printf(_L(" done.\n"));
sl@0
   483
sl@0
   484
	// Check the speed of the physical connection (if any).
sl@0
   485
	gUsingHighSpeed = gPort.CurrentlyUsingHighSpeed();
sl@0
   486
	if (gUsingHighSpeed)
sl@0
   487
		{
sl@0
   488
		test(gSupportsHighSpeed);							// sane?
sl@0
   489
		test.Printf(_L("---> USB High-speed Testing\n"));
sl@0
   490
		}
sl@0
   491
	else
sl@0
   492
		{
sl@0
   493
		test.Printf(_L("---> USB Full-speed Testing\n"));
sl@0
   494
		}
sl@0
   495
sl@0
   496
	// By pulling down the interface/connection and bringing them up again we
sl@0
   497
	// simulate a starting/stopping of the USB service by a control app.
sl@0
   498
sl@0
   499
	test.Next(_L("Disconnecting from Host"));
sl@0
   500
	r = gPort.DeviceDisconnectFromHost();
sl@0
   501
	test(r == KErrNone);
sl@0
   502
sl@0
   503
	test.Next(_L("Releasing interface"));
sl@0
   504
	r = gPort.ReleaseInterface(0);
sl@0
   505
	test(r == KErrNone);
sl@0
   506
sl@0
   507
	test.Next(_L("Setting interface"));
sl@0
   508
	r = gPort.SetInterface(0, ifc);
sl@0
   509
	test(r == KErrNone);
sl@0
   510
sl@0
   511
 	// Suspend thread before connecting again.
sl@0
   512
	test.Printf(_L("Waiting a short moment..."));
sl@0
   513
	User::After(1000000);
sl@0
   514
	test.Printf(_L(" done.\n"));
sl@0
   515
sl@0
   516
	test.Next(_L("Powering up UDC (2)"));
sl@0
   517
	r = gPort.PowerUpUdc();
sl@0
   518
	if (!gSupportsOtg)
sl@0
   519
		{
sl@0
   520
		test(r == KErrNone);
sl@0
   521
		}
sl@0
   522
	else
sl@0
   523
		{
sl@0
   524
		test((r == KErrNone) || (r == KErrNotReady));
sl@0
   525
		}
sl@0
   526
	if (gSupportsOtg && (r == KErrNotReady))
sl@0
   527
		{
sl@0
   528
		test.Printf(_L("OTG device but not connected to Host, stopping subtest here.\n"));
sl@0
   529
		test.End();
sl@0
   530
		return;
sl@0
   531
		}
sl@0
   532
sl@0
   533
	test.Next(_L("Connecting to Host (2)"));
sl@0
   534
	r = gPort.DeviceConnectToHost();
sl@0
   535
	test(r == KErrNone);
sl@0
   536
	// Suspend thread to let things get stable on the bus.
sl@0
   537
	User::After(2000000);
sl@0
   538
sl@0
   539
	test.End();
sl@0
   540
	}
sl@0
   541
sl@0
   542
sl@0
   543
static void TestDeviceDescriptor()
sl@0
   544
	{
sl@0
   545
	test.Start(_L("Device Descriptor Manipulation"));
sl@0
   546
sl@0
   547
	test.Next(_L("GetDeviceDescriptorSize()"));
sl@0
   548
	TInt desc_size = 0;
sl@0
   549
	gPort.GetDeviceDescriptorSize(desc_size);
sl@0
   550
	test(static_cast<TUint>(desc_size) == KUsbDescSize_Device);
sl@0
   551
sl@0
   552
	test.Next(_L("GetDeviceDescriptor()"));
sl@0
   553
	TBuf8<KUsbDescSize_Device> descriptor;
sl@0
   554
	TInt r = gPort.GetDeviceDescriptor(descriptor);
sl@0
   555
	test(r == KErrNone);
sl@0
   556
sl@0
   557
	test.Next(_L("SetDeviceDescriptor()"));
sl@0
   558
	// Change the USB spec number to 2.30
sl@0
   559
	descriptor[KDevDesc_SpecOffset]   = 0x30;
sl@0
   560
	descriptor[KDevDesc_SpecOffset+1] = 0x02;
sl@0
   561
	// Change the device vendor ID (VID) to 0x1234
sl@0
   562
	descriptor[KDevDesc_VendorIdOffset]   = 0x34;			// little endian
sl@0
   563
	descriptor[KDevDesc_VendorIdOffset+1] = 0x12;
sl@0
   564
	// Change the device product ID (PID) to 0x1111
sl@0
   565
	descriptor[KDevDesc_ProductIdOffset]   = 0x11;
sl@0
   566
	descriptor[KDevDesc_ProductIdOffset+1] = 0x11;
sl@0
   567
	// Change the device release number to 3.05
sl@0
   568
	descriptor[KDevDesc_DevReleaseOffset]   = 0x05;
sl@0
   569
	descriptor[KDevDesc_DevReleaseOffset+1] = 0x03;
sl@0
   570
	r = gPort.SetDeviceDescriptor(descriptor);
sl@0
   571
	test(r == KErrNone);
sl@0
   572
sl@0
   573
	test.Next(_L("GetDeviceDescriptor()"));
sl@0
   574
	TBuf8<KUsbDescSize_Device> descriptor2;
sl@0
   575
	r = gPort.GetDeviceDescriptor(descriptor2);
sl@0
   576
	test(r == KErrNone);
sl@0
   577
sl@0
   578
	test.Next(_L("Compare device descriptor with value set"));
sl@0
   579
	r = descriptor2.Compare(descriptor);
sl@0
   580
	test(r == KErrNone);
sl@0
   581
sl@0
   582
	if (gUsingHighSpeed)
sl@0
   583
		{
sl@0
   584
		// HS only allows one possible packet size.
sl@0
   585
		test(descriptor[KDevDesc_Ep0SizeOffset] == 64);
sl@0
   586
		}
sl@0
   587
sl@0
   588
	test.End();
sl@0
   589
	}
sl@0
   590
sl@0
   591
sl@0
   592
static void	TestDeviceQualifierDescriptor()
sl@0
   593
	{
sl@0
   594
	test.Start(_L("Device_Qualifier Descriptor Manipulation"));
sl@0
   595
sl@0
   596
	if (!gSupportsHighSpeed)
sl@0
   597
		{
sl@0
   598
		test.Printf(_L("*** Not supported - skipping Device_Qualifier descriptor tests\n"));
sl@0
   599
		test.End();
sl@0
   600
		return;
sl@0
   601
		}
sl@0
   602
sl@0
   603
	test.Next(_L("GetDeviceQualifierDescriptor()"));
sl@0
   604
	TBuf8<KUsbDescSize_DeviceQualifier> descriptor;
sl@0
   605
	TInt r = gPort.GetDeviceQualifierDescriptor(descriptor);
sl@0
   606
	test(r == KErrNone);
sl@0
   607
sl@0
   608
	test.Next(_L("SetDeviceQualifierDescriptor()"));
sl@0
   609
	// Change the USB spec number to 3.00
sl@0
   610
	descriptor[KDevDesc_SpecOffset]   = 0x00;
sl@0
   611
	descriptor[KDevDesc_SpecOffset+1] = 0x03;
sl@0
   612
	// Change the device class, subclass and protocol codes
sl@0
   613
	descriptor[KDevDesc_DevClassOffset]    = 0xA1;
sl@0
   614
	descriptor[KDevDesc_DevSubClassOffset] = 0xB2;
sl@0
   615
	descriptor[KDevDesc_DevProtocolOffset] = 0xC3;
sl@0
   616
	r = gPort.SetDeviceQualifierDescriptor(descriptor);
sl@0
   617
	test(r == KErrNone);
sl@0
   618
sl@0
   619
	test.Next(_L("GetDeviceQualifierDescriptor()"));
sl@0
   620
	TBuf8<KUsbDescSize_DeviceQualifier> descriptor2;
sl@0
   621
	r = gPort.GetDeviceQualifierDescriptor(descriptor2);
sl@0
   622
	test(r == KErrNone);
sl@0
   623
sl@0
   624
	test.Next(_L("Compare Device_Qualifier desc with value set"));
sl@0
   625
	r = descriptor2.Compare(descriptor);
sl@0
   626
	test(r == 0);
sl@0
   627
sl@0
   628
	if (!gUsingHighSpeed)
sl@0
   629
		{
sl@0
   630
		// HS only allows one possible packet size.
sl@0
   631
		test(descriptor[KDevDesc_Ep0SizeOffset] == 64);
sl@0
   632
		}
sl@0
   633
sl@0
   634
	test.End();
sl@0
   635
	}
sl@0
   636
sl@0
   637
sl@0
   638
static void TestConfigurationDescriptor()
sl@0
   639
	{
sl@0
   640
	test.Start(_L("Configuration Descriptor Manipulation"));
sl@0
   641
sl@0
   642
	test.Next(_L("GetConfigurationDescriptorSize()"));
sl@0
   643
	TInt desc_size = 0;
sl@0
   644
	gPort.GetConfigurationDescriptorSize(desc_size);
sl@0
   645
	test(static_cast<TUint>(desc_size) == KUsbDescSize_Config);
sl@0
   646
sl@0
   647
	test.Next(_L("GetConfigurationDescriptor()"));
sl@0
   648
	TBuf8<KUsbDescSize_Config> descriptor;
sl@0
   649
	TInt r = gPort.GetConfigurationDescriptor(descriptor);
sl@0
   650
	test(r == KErrNone);
sl@0
   651
sl@0
   652
	test.Next(_L("SetConfigurationDescriptor()"));
sl@0
   653
	// Invert Remote-Wakup support
sl@0
   654
	descriptor[KConfDesc_AttribOffset] = (descriptor[KConfDesc_AttribOffset] ^ KUsbDevAttr_RemoteWakeup);
sl@0
   655
	// Change the reported max power to 200mA (2 * 0x64)
sl@0
   656
	descriptor[KConfDesc_MaxPowerOffset] = 0x64;
sl@0
   657
	r = gPort.SetConfigurationDescriptor(descriptor);
sl@0
   658
	test(r == KErrNone);
sl@0
   659
sl@0
   660
	test.Next(_L("GetConfigurationDescriptor()"));
sl@0
   661
	TBuf8<KUsbDescSize_Config> descriptor2;
sl@0
   662
	r = gPort.GetConfigurationDescriptor(descriptor2);
sl@0
   663
	test(r == KErrNone);
sl@0
   664
sl@0
   665
	test.Next(_L("Compare configuration desc with value set"));
sl@0
   666
	r = descriptor2.Compare(descriptor);
sl@0
   667
	test(r == KErrNone);
sl@0
   668
sl@0
   669
	test.End();
sl@0
   670
	}
sl@0
   671
sl@0
   672
sl@0
   673
static void	TestOtherSpeedConfigurationDescriptor()
sl@0
   674
	{
sl@0
   675
	test.Start(_L("Other_Speed_Configuration Desc Manipulation"));
sl@0
   676
sl@0
   677
	if (!gSupportsHighSpeed)
sl@0
   678
		{
sl@0
   679
		test.Printf(_L("*** Not supported - skipping Other_Speed_Configuration desc tests\n"));
sl@0
   680
		test.End();
sl@0
   681
		return;
sl@0
   682
		}
sl@0
   683
sl@0
   684
	test.Next(_L("GetOtherSpeedConfigurationDescriptor()"));
sl@0
   685
	TBuf8<KUsbDescSize_OtherSpeedConfig> descriptor;
sl@0
   686
	TInt r = gPort.GetOtherSpeedConfigurationDescriptor(descriptor);
sl@0
   687
	test(r == KErrNone);
sl@0
   688
sl@0
   689
	test.Next(_L("SetOtherSpeedConfigurationDescriptor()"));
sl@0
   690
	// Invert Remote-Wakup support
sl@0
   691
	descriptor[KConfDesc_AttribOffset] = (descriptor[KConfDesc_AttribOffset] ^ KUsbDevAttr_RemoteWakeup);
sl@0
   692
	// Change the reported max power to 330mA (2 * 0xA5)
sl@0
   693
	descriptor[KConfDesc_MaxPowerOffset] = 0xA5;
sl@0
   694
	r = gPort.SetOtherSpeedConfigurationDescriptor(descriptor);
sl@0
   695
	test(r == KErrNone);
sl@0
   696
sl@0
   697
	test.Next(_L("GetOtherSpeedConfigurationDescriptor()"));
sl@0
   698
	TBuf8<KUsbDescSize_OtherSpeedConfig> descriptor2;
sl@0
   699
	r = gPort.GetOtherSpeedConfigurationDescriptor(descriptor2);
sl@0
   700
	test(r == KErrNone);
sl@0
   701
sl@0
   702
	test.Next(_L("Compare O_S_Config desc with value set"));
sl@0
   703
	r = descriptor2.Compare(descriptor);
sl@0
   704
	test(r == KErrNone);
sl@0
   705
sl@0
   706
	test.End();
sl@0
   707
	}
sl@0
   708
sl@0
   709
sl@0
   710
static void TestInterfaceDescriptor()
sl@0
   711
	{
sl@0
   712
	test.Start(_L("Interface Descriptor Manipulation"));
sl@0
   713
sl@0
   714
	// First the standard Interface descriptor
sl@0
   715
sl@0
   716
	test.Next(_L("GetInterfaceDescriptorSize()"));
sl@0
   717
	TInt desc_size = 0;
sl@0
   718
	TInt r = gPort.GetInterfaceDescriptorSize(0, desc_size);
sl@0
   719
	test(r == KErrNone);
sl@0
   720
	test(static_cast<TUint>(desc_size) == KUsbDescSize_Interface);
sl@0
   721
sl@0
   722
	test.Next(_L("GetInterfaceDescriptor()"));
sl@0
   723
	TBuf8<KUsbDescSize_Interface> descriptor;
sl@0
   724
	r = gPort.GetInterfaceDescriptor(0, descriptor);
sl@0
   725
	test(r == KErrNone);
sl@0
   726
sl@0
   727
	test.Next(_L("SetInterfaceDescriptor()"));
sl@0
   728
	// Change the interface protocol to 0x78(+)
sl@0
   729
	TUint8 prot = 0x78;
sl@0
   730
	if (descriptor[KIfcDesc_ProtocolOffset] == prot)
sl@0
   731
		prot++;
sl@0
   732
	descriptor[KIfcDesc_ProtocolOffset] = prot;
sl@0
   733
	r = gPort.SetInterfaceDescriptor(0, descriptor);
sl@0
   734
	test(r == KErrNone);
sl@0
   735
sl@0
   736
	test.Next(_L("GetInterfaceDescriptor()"));
sl@0
   737
	TBuf8<KUsbDescSize_Interface> descriptor2;
sl@0
   738
	r = gPort.GetInterfaceDescriptor(0, descriptor2);
sl@0
   739
	test(r == KErrNone);
sl@0
   740
sl@0
   741
	test.Next(_L("Compare interface descriptor with value set"));
sl@0
   742
	r = descriptor2.Compare(descriptor);
sl@0
   743
	test(r == KErrNone);
sl@0
   744
sl@0
   745
	test.End();
sl@0
   746
	}
sl@0
   747
sl@0
   748
sl@0
   749
static void TestClassSpecificDescriptors()
sl@0
   750
	{
sl@0
   751
	test.Start(_L("Class-specific Descriptor Manipulation"));
sl@0
   752
sl@0
   753
	// First a class-specific Interface descriptor
sl@0
   754
sl@0
   755
	test.Next(_L("SetCSInterfaceDescriptorBlock()"));
sl@0
   756
	// choose arbitrary new descriptor size
sl@0
   757
	const TInt KUsbDescSize_CS_Interface = KUsbDescSize_Interface + 10;
sl@0
   758
	TBuf8<KUsbDescSize_CS_Interface> cs_ifc_descriptor;
sl@0
   759
	cs_ifc_descriptor.FillZ(cs_ifc_descriptor.MaxLength());
sl@0
   760
	cs_ifc_descriptor[KUsbDesc_SizeOffset] = KUsbDescSize_CS_Interface;
sl@0
   761
	cs_ifc_descriptor[KUsbDesc_TypeOffset] = KUsbDescType_CS_Interface;
sl@0
   762
	TInt r = gPort.SetCSInterfaceDescriptorBlock(0, cs_ifc_descriptor);
sl@0
   763
	test(r == KErrNone);
sl@0
   764
sl@0
   765
	test.Next(_L("GetCSInterfaceDescriptorBlockSize()"));
sl@0
   766
	TInt desc_size = 0;
sl@0
   767
	r = gPort.GetCSInterfaceDescriptorBlockSize(0, desc_size);
sl@0
   768
	test(r == KErrNone);
sl@0
   769
	test(desc_size == KUsbDescSize_CS_Interface);
sl@0
   770
sl@0
   771
	test.Next(_L("GetCSInterfaceDescriptorBlock()"));
sl@0
   772
	TBuf8<KUsbDescSize_CS_Interface> descriptor;
sl@0
   773
	r = gPort.GetCSInterfaceDescriptorBlock(0, descriptor);
sl@0
   774
	test(r == KErrNone);
sl@0
   775
sl@0
   776
	test.Next(_L("Compare CS ifc descriptor with value set"));
sl@0
   777
	r = descriptor.Compare(cs_ifc_descriptor);
sl@0
   778
	test(r == KErrNone);
sl@0
   779
sl@0
   780
	// Next a class-specific Endpoint descriptor
sl@0
   781
sl@0
   782
	test.Next(_L("SetCSEndpointDescriptorBlock()"));
sl@0
   783
	// choose arbitrary new descriptor size
sl@0
   784
	const TInt KUsbDescSize_CS_Endpoint = KUsbDescSize_Endpoint + 5;
sl@0
   785
	TBuf8<KUsbDescSize_CS_Endpoint> cs_ep_descriptor;
sl@0
   786
	cs_ep_descriptor.FillZ(cs_ep_descriptor.MaxLength());
sl@0
   787
	cs_ep_descriptor[KUsbDesc_SizeOffset] = KUsbDescSize_CS_Endpoint;
sl@0
   788
	cs_ep_descriptor[KUsbDesc_TypeOffset] = KUsbDescType_CS_Endpoint;
sl@0
   789
	r = gPort.SetCSEndpointDescriptorBlock(0, 2, cs_ep_descriptor);
sl@0
   790
	test(r == KErrNone);
sl@0
   791
sl@0
   792
	test.Next(_L("GetCSEndpointDescriptorBlockSize()"));
sl@0
   793
	r = gPort.GetCSEndpointDescriptorBlockSize(0, 2, desc_size);
sl@0
   794
	test(r == KErrNone);
sl@0
   795
	test(desc_size == KUsbDescSize_CS_Endpoint);
sl@0
   796
sl@0
   797
	test.Next(_L("GetCSEndpointDescriptorBlock()"));
sl@0
   798
	TBuf8<KUsbDescSize_CS_Endpoint> descriptor2;
sl@0
   799
	r = gPort.GetCSEndpointDescriptorBlock(0, 2, descriptor2);
sl@0
   800
	test(r == KErrNone);
sl@0
   801
sl@0
   802
	test.Next(_L("Compare CS ep descriptor with value set"));
sl@0
   803
	r = descriptor2.Compare(cs_ep_descriptor);
sl@0
   804
	test(r == KErrNone);
sl@0
   805
sl@0
   806
	test.End();
sl@0
   807
	}
sl@0
   808
sl@0
   809
sl@0
   810
static void TestAlternateInterfaceManipulation()
sl@0
   811
	{
sl@0
   812
	test.Start(_L("Alternate Interface Setting Manipulation"));
sl@0
   813
sl@0
   814
	if (!SupportsAlternateInterfaces())
sl@0
   815
		{
sl@0
   816
		test.Printf(_L("*** Not supported - skipping alternate interface settings tests\n"));
sl@0
   817
		test.End();
sl@0
   818
		return;
sl@0
   819
		}
sl@0
   820
sl@0
   821
	// Fetch endpoint data (again)
sl@0
   822
	test.Next(_L("Get endpoint capabilities"));
sl@0
   823
	TUsbDeviceCaps d_caps;
sl@0
   824
	TInt r = gPort.DeviceCaps(d_caps);
sl@0
   825
	test(r == KErrNone);
sl@0
   826
	const TInt n = d_caps().iTotalEndpoints;
sl@0
   827
	TUsbcEndpointData data[KUsbcMaxEndpoints];
sl@0
   828
	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
sl@0
   829
	r = gPort.EndpointCaps(dataptr);
sl@0
   830
	test(r == KErrNone);
sl@0
   831
sl@0
   832
	// Find ep's for alternate ifc setting
sl@0
   833
	test.Next(_L("Find suitable endpoints"));
sl@0
   834
	TInt ep_found = 0;
sl@0
   835
	TBool foundIsoIN  = EFalse;
sl@0
   836
	TBool foundIsoOUT = EFalse;
sl@0
   837
	TBool foundIntIN  = EFalse;
sl@0
   838
	TUsbcInterfaceInfoBuf ifc;
sl@0
   839
sl@0
   840
	// NB! We cannot assume that any specific device has any given set of
sl@0
   841
	// capabilities, so whilst we try and set an assortment of endpoint types
sl@0
   842
	// we may not get what we want.
sl@0
   843
sl@0
   844
	// Also, note that the endpoint[] array in the interface descriptor
sl@0
   845
	// must be filled from ep[0]...ep[n-1].
sl@0
   846
sl@0
   847
	for (TInt i = 0; i < n; i++)
sl@0
   848
		{
sl@0
   849
		const TUsbcEndpointCaps* const caps = &data[i].iCaps;
sl@0
   850
		const TInt mps = caps->MaxPacketSize();
sl@0
   851
		if (!foundIsoIN &&
sl@0
   852
			(caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirIn)) ==
sl@0
   853
			(KUsbEpTypeIsochronous | KUsbEpDirIn))
sl@0
   854
			{
sl@0
   855
			// This is going to be our Iso TX (IN) endpoint
sl@0
   856
			ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
sl@0
   857
			ifc().iEndpointData[ep_found].iDir  = KUsbEpDirIn;
sl@0
   858
			ifc().iEndpointData[ep_found].iSize = mps;
sl@0
   859
			ifc().iEndpointData[ep_found].iInterval = 0x01;	// 2^(bInterval-1)ms, bInterval must be [1..16]
sl@0
   860
			ifc().iEndpointData[ep_found].iInterval_Hs = 0x01; // same as for FS
sl@0
   861
			test.Printf(_L("ISO  IN  size = %4d (ep %d)\n"), mps, ep_found + 1);
sl@0
   862
			foundIsoIN = ETrue;
sl@0
   863
			if (++ep_found == 3)
sl@0
   864
				break;
sl@0
   865
			}
sl@0
   866
		else if (!foundIsoOUT &&
sl@0
   867
				 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirOut)) ==
sl@0
   868
				 (KUsbEpTypeIsochronous | KUsbEpDirOut))
sl@0
   869
			{
sl@0
   870
			// This is going to be our Iso RX (OUT) endpoint
sl@0
   871
			ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
sl@0
   872
			ifc().iEndpointData[ep_found].iDir  = KUsbEpDirOut;
sl@0
   873
			ifc().iEndpointData[ep_found].iSize = mps;
sl@0
   874
			ifc().iEndpointData[ep_found].iInterval = 0x01;	// 2^(bInterval-1)ms, bInterval must be [1..16]
sl@0
   875
			test.Printf(_L("ISO  OUT size = %4d (ep %d)\n"), mps, ep_found + 1);
sl@0
   876
			foundIsoOUT = ETrue;
sl@0
   877
			if (++ep_found == 3)
sl@0
   878
				break;
sl@0
   879
			}
sl@0
   880
		else if (!foundIntIN &&
sl@0
   881
				 (caps->iTypesAndDir & (KUsbEpTypeInterrupt | KUsbEpDirIn)) ==
sl@0
   882
				 (KUsbEpTypeInterrupt | KUsbEpDirIn))
sl@0
   883
			{
sl@0
   884
			// This is going to be our Interrupt TX (IN) endpoint
sl@0
   885
			ifc().iEndpointData[ep_found].iType  = KUsbEpTypeInterrupt;
sl@0
   886
			ifc().iEndpointData[ep_found].iDir   = KUsbEpDirIn;
sl@0
   887
			ifc().iEndpointData[ep_found].iSize  = mps;
sl@0
   888
			ifc().iEndpointData[ep_found].iInterval = 10;	// interval = 10ms, valid range [1..255]
sl@0
   889
			ifc().iEndpointData[ep_found].iInterval_Hs = 4;	// interval = 2^(bInterval-1)ms = 8ms
sl@0
   890
			ifc().iEndpointData[ep_found].iExtra    = 2;	// 2 extra bytes for Audio Class EP descriptor
sl@0
   891
			test.Printf(_L("INT  IN  size = %4d (ep %d)\n"), mps, ep_found + 1);
sl@0
   892
			foundIntIN = ETrue;
sl@0
   893
			INT_IN_ep = ep_found + 1;
sl@0
   894
			if (++ep_found == 3)
sl@0
   895
				break;
sl@0
   896
			}
sl@0
   897
		}
sl@0
   898
sl@0
   899
	// Let's try to add some more Bulk endpoints up to the max # of 5.
sl@0
   900
	for (TInt i = 0; i < n; i++)
sl@0
   901
		{
sl@0
   902
		TUsbcEndpointCaps& caps = data[i].iCaps;
sl@0
   903
		const TUint mps = caps.MaxPacketSize();
sl@0
   904
		if (caps.iTypesAndDir & KUsbEpTypeBulk)
sl@0
   905
			{
sl@0
   906
			const TUint dir = (caps.iTypesAndDir & KUsbEpDirIn) ? KUsbEpDirIn : KUsbEpDirOut;
sl@0
   907
			ifc().iEndpointData[ep_found].iType = KUsbEpTypeBulk;
sl@0
   908
			ifc().iEndpointData[ep_found].iDir = dir;
sl@0
   909
			if (gUsingHighSpeed)
sl@0
   910
				{
sl@0
   911
				test.Printf(_L("Checking if correct Bulk packet size is reported in HS case\n"));
sl@0
   912
				test(mps == KUsbEpSize512);					// sane?
sl@0
   913
				}
sl@0
   914
			// The PSL should in any case also offer the 'legacy' FS size:
sl@0
   915
			test(caps.iSizes & KUsbEpSize64);
sl@0
   916
			ifc().iEndpointData[ep_found].iSize = mps;
sl@0
   917
			test.Printf(_L("BULK %s size = %4d (ep %d)\n"),
sl@0
   918
						dir == KUsbEpDirIn ? _S("IN ") : _S("OUT"), mps, ep_found + 1);
sl@0
   919
			if (++ep_found == 5)
sl@0
   920
				break;
sl@0
   921
			}
sl@0
   922
		}
sl@0
   923
sl@0
   924
	test.Printf(_L("Total: %d endpoints found for the alt. ifc setting\n"), ep_found);
sl@0
   925
	if (ep_found < 3)
sl@0
   926
		{
sl@0
   927
		test.Printf(_L("(3 endpoints are at least required. Skipping test...)\n"));
sl@0
   928
		test.End();
sl@0
   929
		return;
sl@0
   930
		}
sl@0
   931
sl@0
   932
	if (!foundIsoIN && !foundIsoOUT)
sl@0
   933
		{
sl@0
   934
		test.Printf(_L("(No Isochronous endpoints found)\n"));
sl@0
   935
		}
sl@0
   936
sl@0
   937
	if (!foundIntIN)
sl@0
   938
		{
sl@0
   939
		test.Printf(_L("(No Interrupt endpoint found)\n"));
sl@0
   940
		test.Printf(_L("Adjusting endpoint size for later test\n"));
sl@0
   941
		// We want to make sure that at least one descriptor has the 2 extra bytes.
sl@0
   942
		// It doesn't matter that this ep could be a Bulk one, or that the 2 Iso ep's might be missing -
sl@0
   943
		// we just want to test some functionality and we're not going to use this interface in earnest.
sl@0
   944
		ifc().iEndpointData[2].iExtra = 2;					// 2 extra bytes for Audio Class Ep descriptor
sl@0
   945
		INT_IN_ep = 3;										// pretend it's an INT ep
sl@0
   946
		}
sl@0
   947
sl@0
   948
	test.Next(_L("Create alternate interface setting"));
sl@0
   949
	_LIT16(string, "T_USBAPI Test Interface (Setting 1: Audio)");
sl@0
   950
	ifc().iString = const_cast<TDesC16*>(&string);
sl@0
   951
	ifc().iTotalEndpointsUsed = ep_found;
sl@0
   952
	ifc().iClass.iClassNum	  = KUsbAudioInterfaceClassCode;
sl@0
   953
	ifc().iClass.iSubClassNum = KUsbAudioInterfaceSubclassCode_Audiostreaming;
sl@0
   954
	ifc().iClass.iProtocolNum = KUsbAudioInterfaceProtocolCode_Pr_Protocol_Undefined;
sl@0
   955
	r = gPort.SetInterface(1, ifc);
sl@0
   956
	test(r == KErrNone);
sl@0
   957
sl@0
   958
	test.Next(_L("Set alternate setting number to 8"));
sl@0
   959
	TBuf8<KUsbDescSize_Interface> descriptor;
sl@0
   960
	r = gPort.GetInterfaceDescriptor(1, descriptor);
sl@0
   961
	test(r == KErrNone);
sl@0
   962
	descriptor[KIfcDesc_SettingOffset] = 8;
sl@0
   963
	r = gPort.SetInterfaceDescriptor(1, descriptor);
sl@0
   964
	test(r != KErrNone);
sl@0
   965
sl@0
   966
	test.Next(_L("Change ifc # in def setting whith alt ifcs"));
sl@0
   967
	r = gPort.GetInterfaceDescriptor(0, descriptor);
sl@0
   968
	test(r == KErrNone);
sl@0
   969
	descriptor[KIfcDesc_SettingOffset] = 8;
sl@0
   970
	r = gPort.SetInterfaceDescriptor(0, descriptor);
sl@0
   971
	test(r != KErrNone);
sl@0
   972
sl@0
   973
	test.Next(_L("Change the ifc # in default setting to 8"));
sl@0
   974
	r = gPort.ReleaseInterface(1);
sl@0
   975
	test(r == KErrNone);
sl@0
   976
	r = gPort.SetInterfaceDescriptor(0, descriptor);
sl@0
   977
	test(r == KErrNone);
sl@0
   978
sl@0
   979
	test.Next(_L("Create new setting - this should also get #8"));
sl@0
   980
	r = gPort.SetInterface(1, ifc);
sl@0
   981
	test(r == KErrNone);
sl@0
   982
	r = gPort.GetInterfaceDescriptor(1, descriptor);
sl@0
   983
	test(r == KErrNone);
sl@0
   984
	test(descriptor[KIfcDesc_SettingOffset] == 8);
sl@0
   985
sl@0
   986
	test.Next(_L("Change the ifc # in default setting to 0"));
sl@0
   987
	r = gPort.ReleaseInterface(1);
sl@0
   988
	test(r == KErrNone);
sl@0
   989
	r = gPort.GetInterfaceDescriptor(0, descriptor);
sl@0
   990
	test(r == KErrNone);
sl@0
   991
	descriptor[KIfcDesc_SettingOffset] = 0;
sl@0
   992
	r = gPort.SetInterfaceDescriptor(0, descriptor);
sl@0
   993
	test(r == KErrNone);
sl@0
   994
sl@0
   995
	test.Next(_L("Create new setting - this should also get #0"));
sl@0
   996
	r = gPort.SetInterface(1, ifc);
sl@0
   997
	test(r == KErrNone);
sl@0
   998
	r = gPort.GetInterfaceDescriptor(1, descriptor);
sl@0
   999
	test(r == KErrNone);
sl@0
  1000
	test(descriptor[KIfcDesc_SettingOffset] == 0);
sl@0
  1001
sl@0
  1002
	test.End();
sl@0
  1003
	}
sl@0
  1004
sl@0
  1005
sl@0
  1006
static void TestEndpointDescriptor()
sl@0
  1007
	{
sl@0
  1008
	test.Start(_L("Endpoint Descriptor Manipulation"));
sl@0
  1009
sl@0
  1010
	test.Next(_L("GetEndpointDescriptorSize(1)"));
sl@0
  1011
	TInt epNumber = 1;
sl@0
  1012
	TInt desc_size = 0;
sl@0
  1013
	TInt r = gPort.GetEndpointDescriptorSize(0, epNumber, desc_size);
sl@0
  1014
	test(r == KErrNone);
sl@0
  1015
	test(static_cast<TUint>(desc_size) == KUsbDescSize_Endpoint);
sl@0
  1016
sl@0
  1017
	test.Next(_L("GetEndpointDescriptor(1)"));
sl@0
  1018
	TBuf8<KUsbDescSize_Endpoint> descriptor;
sl@0
  1019
	r = gPort.GetEndpointDescriptor(0, epNumber, descriptor);
sl@0
  1020
	test(r == KErrNone);
sl@0
  1021
sl@0
  1022
	test.Next(_L("SetEndpointDescriptor(1)"));
sl@0
  1023
	// Change the endpoint poll interval
sl@0
  1024
	TUint8 ival = 0x66;
sl@0
  1025
	if (descriptor[KEpDesc_IntervalOffset] == ival)
sl@0
  1026
		ival++;
sl@0
  1027
	descriptor[KEpDesc_IntervalOffset] = ival;
sl@0
  1028
	r = gPort.SetEndpointDescriptor(0, epNumber, descriptor);
sl@0
  1029
	test(r == KErrNone);
sl@0
  1030
sl@0
  1031
	test.Next(_L("GetEndpointDescriptor(1)"));
sl@0
  1032
	TBuf8<KUsbDescSize_Endpoint> descriptor2;
sl@0
  1033
	r = gPort.GetEndpointDescriptor(0, epNumber, descriptor2);
sl@0
  1034
	test(r == KErrNone);
sl@0
  1035
sl@0
  1036
	test.Next(_L("Compare endpoint descriptor with value set"));
sl@0
  1037
	r = descriptor2.Compare(descriptor);
sl@0
  1038
	test(r == KErrNone);
sl@0
  1039
sl@0
  1040
	test.Next(_L("Check endpoint max packet size"));
sl@0
  1041
	const TUint16 ep_size = EpSize(descriptor[KEpDesc_PacketSizeOffset],
sl@0
  1042
								   descriptor[KEpDesc_PacketSizeOffset+1]);
sl@0
  1043
	test.Printf(_L(" Size: %d\n"), ep_size);
sl@0
  1044
	if (gUsingHighSpeed)
sl@0
  1045
		{
sl@0
  1046
		// HS Bulk ep can only have one possible packet size.
sl@0
  1047
		test(ep_size == 512);
sl@0
  1048
		}
sl@0
  1049
	else
sl@0
  1050
		{
sl@0
  1051
		// FS Bulk ep cannot be larger than 64 bytes.
sl@0
  1052
		test(ep_size <= 64);
sl@0
  1053
		}
sl@0
  1054
sl@0
  1055
	test.End();
sl@0
  1056
	}
sl@0
  1057
sl@0
  1058
sl@0
  1059
static void TestExtendedEndpointDescriptor()
sl@0
  1060
	{
sl@0
  1061
	test.Start(_L("Extended Endpoint Descriptor Manipulation"));
sl@0
  1062
sl@0
  1063
	if (!SupportsAlternateInterfaces())
sl@0
  1064
		{
sl@0
  1065
		test.Printf(_L("*** Not supported - skipping Extended Endpoint descriptor tests\n"));
sl@0
  1066
		test.End();
sl@0
  1067
		return;
sl@0
  1068
		}
sl@0
  1069
sl@0
  1070
	// Extended Endpoint Descriptor manipulation (Audio class endpoint)
sl@0
  1071
sl@0
  1072
	test.Next(_L("GetEndpointDescriptorSize()"));
sl@0
  1073
	TInt epNumber = INT_IN_ep;
sl@0
  1074
	TInt desc_size = 0;
sl@0
  1075
	TInt r = gPort.GetEndpointDescriptorSize(1, epNumber, desc_size);
sl@0
  1076
	test(r == KErrNone);
sl@0
  1077
	test(static_cast<TUint>(desc_size) == KUsbDescSize_AudioEndpoint);
sl@0
  1078
sl@0
  1079
	test.Next(_L("GetEndpointDescriptor()"));
sl@0
  1080
	TBuf8<KUsbDescSize_AudioEndpoint> descriptor;
sl@0
  1081
	r = gPort.GetEndpointDescriptor(1, epNumber, descriptor);
sl@0
  1082
	test(r == KErrNone);
sl@0
  1083
sl@0
  1084
	test.Next(_L("SetEndpointDescriptor()"));
sl@0
  1085
	// Change the Audio Endpoint bSynchAddress field
sl@0
  1086
	TUint8 addr = 0x85;										// bogus address
sl@0
  1087
	if (descriptor[KEpDesc_SynchAddressOffset] == addr)
sl@0
  1088
		addr++;
sl@0
  1089
	descriptor[KEpDesc_SynchAddressOffset] = addr;
sl@0
  1090
	r = gPort.SetEndpointDescriptor(1, epNumber, descriptor);
sl@0
  1091
	test(r == KErrNone);
sl@0
  1092
sl@0
  1093
	test.Next(_L("GetEndpointDescriptor()"));
sl@0
  1094
	TBuf8<KUsbDescSize_AudioEndpoint> descriptor2;
sl@0
  1095
	r = gPort.GetEndpointDescriptor(1, epNumber, descriptor2);
sl@0
  1096
	test(r == KErrNone);
sl@0
  1097
sl@0
  1098
	test.Next(_L("Compare endpoint descriptor with value set"));
sl@0
  1099
	r = descriptor2.Compare(descriptor);
sl@0
  1100
	test(r == KErrNone);
sl@0
  1101
sl@0
  1102
	test.Next(_L("Check endpoint max packet size"));
sl@0
  1103
	const TUint16 ep_size = EpSize(descriptor[KEpDesc_PacketSizeOffset],
sl@0
  1104
								   descriptor[KEpDesc_PacketSizeOffset+1]);
sl@0
  1105
	if (gUsingHighSpeed)
sl@0
  1106
		{
sl@0
  1107
		// HS Interrupt ep.
sl@0
  1108
		test(ep_size <= 1024);
sl@0
  1109
		}
sl@0
  1110
	else
sl@0
  1111
		{
sl@0
  1112
		// FS Interrupt ep cannot be larger than 64 bytes.
sl@0
  1113
		test(ep_size <= 64);
sl@0
  1114
		}
sl@0
  1115
sl@0
  1116
	test.End();
sl@0
  1117
	}
sl@0
  1118
sl@0
  1119
sl@0
  1120
static void TestStandardStringDescriptors()
sl@0
  1121
	{
sl@0
  1122
	test.Start(_L("String Descriptor Manipulation"));
sl@0
  1123
sl@0
  1124
	//
sl@0
  1125
	// --- LANGID code
sl@0
  1126
	//
sl@0
  1127
sl@0
  1128
	test.Next(_L("GetStringDescriptorLangId()"));
sl@0
  1129
	TUint16 rd_langid_orig;
sl@0
  1130
	TInt r = gPort.GetStringDescriptorLangId(rd_langid_orig);
sl@0
  1131
	test(r == KErrNone);
sl@0
  1132
	test.Printf(_L("Original LANGID code: 0x%04X\n"), rd_langid_orig);
sl@0
  1133
sl@0
  1134
	test.Next(_L("SetStringDescriptorLangId()"));
sl@0
  1135
	TUint16 wr_langid = 0x0809;								// English (UK) Language ID
sl@0
  1136
	if (wr_langid == rd_langid_orig)
sl@0
  1137
		wr_langid = 0x0444;									// Tatar Language ID
sl@0
  1138
	r = gPort.SetStringDescriptorLangId(wr_langid);
sl@0
  1139
	test(r == KErrNone);
sl@0
  1140
sl@0
  1141
	test.Next(_L("GetStringDescriptorLangId()"));
sl@0
  1142
	TUint16 rd_langid;
sl@0
  1143
	r = gPort.GetStringDescriptorLangId(rd_langid);
sl@0
  1144
	test(r == KErrNone);
sl@0
  1145
	test.Printf(_L("New LANGID code: 0x%04X\n"), rd_langid);
sl@0
  1146
sl@0
  1147
	test.Next(_L("Compare LANGID codes"));
sl@0
  1148
	test(rd_langid == wr_langid);
sl@0
  1149
sl@0
  1150
	test.Next(_L("Restore original LANGID code"));
sl@0
  1151
	r = gPort.SetStringDescriptorLangId(rd_langid_orig);
sl@0
  1152
	test(r == KErrNone);
sl@0
  1153
	r = gPort.GetStringDescriptorLangId(rd_langid);
sl@0
  1154
	test(r == KErrNone);
sl@0
  1155
	test(rd_langid == rd_langid_orig);
sl@0
  1156
sl@0
  1157
	//
sl@0
  1158
	// --- Manufacturer string
sl@0
  1159
	//
sl@0
  1160
sl@0
  1161
	test.Next(_L("GetManufacturerStringDescriptor()"));
sl@0
  1162
	TBuf16<KUsbStringDescStringMaxSize / 2> rd_str_orig;
sl@0
  1163
	r = gPort.GetManufacturerStringDescriptor(rd_str_orig);
sl@0
  1164
	test(r == KErrNone || r == KErrNotFound);
sl@0
  1165
	TBool restore_string;
sl@0
  1166
	if (r == KErrNone)
sl@0
  1167
		{
sl@0
  1168
		test.Printf(_L("Original Manufacturer string: \"%lS\"\n"), &rd_str_orig);
sl@0
  1169
		restore_string = ETrue;
sl@0
  1170
		}
sl@0
  1171
	else
sl@0
  1172
		{
sl@0
  1173
		test.Printf(_L("No Manufacturer string set\n"));
sl@0
  1174
		restore_string = EFalse;
sl@0
  1175
		}
sl@0
  1176
sl@0
  1177
	test.Next(_L("SetManufacturerStringDescriptor()"));
sl@0
  1178
	_LIT16(manufacturer, "Manufacturer Which Manufactures Devices");
sl@0
  1179
	TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(manufacturer);
sl@0
  1180
	r = gPort.SetManufacturerStringDescriptor(wr_str);
sl@0
  1181
	test(r == KErrNone);
sl@0
  1182
sl@0
  1183
	test.Next(_L("GetManufacturerStringDescriptor()"));
sl@0
  1184
	TBuf16<KUsbStringDescStringMaxSize / 2> rd_str;
sl@0
  1185
	r = gPort.GetManufacturerStringDescriptor(rd_str);
sl@0
  1186
	test(r == KErrNone);
sl@0
  1187
	test.Printf(_L("New Manufacturer string: \"%lS\"\n"), &rd_str);
sl@0
  1188
sl@0
  1189
	test.Next(_L("Compare Manufacturer strings"));
sl@0
  1190
	r = rd_str.Compare(wr_str);
sl@0
  1191
	test(r == KErrNone);
sl@0
  1192
sl@0
  1193
	test.Next(_L("SetManufacturerStringDescriptor()"));
sl@0
  1194
	_LIT16(manufacturer2, "Different Manufacturer Which Manufactures Different Devices");
sl@0
  1195
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1196
	wr_str = manufacturer2;
sl@0
  1197
	r = gPort.SetManufacturerStringDescriptor(wr_str);
sl@0
  1198
	test(r == KErrNone);
sl@0
  1199
sl@0
  1200
	test.Next(_L("GetManufacturerStringDescriptor()"));
sl@0
  1201
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1202
	r = gPort.GetManufacturerStringDescriptor(rd_str);
sl@0
  1203
	test(r == KErrNone);
sl@0
  1204
	test.Printf(_L("New Manufacturer string: \"%lS\"\n"), &rd_str);
sl@0
  1205
sl@0
  1206
	test.Next(_L("Compare Manufacturer strings"));
sl@0
  1207
	r = rd_str.Compare(wr_str);
sl@0
  1208
	test(r == KErrNone);
sl@0
  1209
sl@0
  1210
	test.Next(_L("RemoveManufacturerStringDescriptor()"));
sl@0
  1211
	r = gPort.RemoveManufacturerStringDescriptor();
sl@0
  1212
	test(r == KErrNone);
sl@0
  1213
	r = gPort.GetManufacturerStringDescriptor(rd_str);
sl@0
  1214
	test(r == KErrNotFound);
sl@0
  1215
sl@0
  1216
	if (restore_string)
sl@0
  1217
		{
sl@0
  1218
		test.Next(_L("Restore original string"));
sl@0
  1219
		r = gPort.SetManufacturerStringDescriptor(rd_str_orig);
sl@0
  1220
		test(r == KErrNone);
sl@0
  1221
		r = gPort.GetManufacturerStringDescriptor(rd_str);
sl@0
  1222
		test(r == KErrNone);
sl@0
  1223
		r = rd_str.Compare(rd_str_orig);
sl@0
  1224
		test(r == KErrNone);
sl@0
  1225
		}
sl@0
  1226
sl@0
  1227
	//
sl@0
  1228
	// --- Product string
sl@0
  1229
	//
sl@0
  1230
sl@0
  1231
	test.Next(_L("GetProductStringDescriptor()"));
sl@0
  1232
	rd_str_orig.FillZ(rd_str.MaxLength());
sl@0
  1233
	r = gPort.GetProductStringDescriptor(rd_str_orig);
sl@0
  1234
	test(r == KErrNone || r == KErrNotFound);
sl@0
  1235
	if (r == KErrNone)
sl@0
  1236
		{
sl@0
  1237
		test.Printf(_L("Old Product string: \"%lS\"\n"), &rd_str_orig);
sl@0
  1238
		restore_string = ETrue;
sl@0
  1239
		}
sl@0
  1240
	else
sl@0
  1241
		restore_string = EFalse;
sl@0
  1242
sl@0
  1243
	test.Next(_L("SetProductStringDescriptor()"));
sl@0
  1244
	_LIT16(product, "Product That Was Produced By A Manufacturer");
sl@0
  1245
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1246
	wr_str = product;
sl@0
  1247
	r = gPort.SetProductStringDescriptor(wr_str);
sl@0
  1248
	test(r == KErrNone);
sl@0
  1249
sl@0
  1250
	test.Next(_L("GetProductStringDescriptor()"));
sl@0
  1251
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1252
	r = gPort.GetProductStringDescriptor(rd_str);
sl@0
  1253
	test(r == KErrNone);
sl@0
  1254
	test.Printf(_L("New Product string: \"%lS\"\n"), &rd_str);
sl@0
  1255
sl@0
  1256
	test.Next(_L("Compare Product strings"));
sl@0
  1257
	r = rd_str.Compare(wr_str);
sl@0
  1258
	test(r == KErrNone);
sl@0
  1259
sl@0
  1260
	test.Next(_L("SetProductStringDescriptor()"));
sl@0
  1261
	_LIT16(product2, "Different Product That Was Produced By A Different Manufacturer");
sl@0
  1262
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1263
	wr_str = product2;
sl@0
  1264
	r = gPort.SetProductStringDescriptor(wr_str);
sl@0
  1265
	test(r == KErrNone);
sl@0
  1266
sl@0
  1267
	test.Next(_L("GetProductStringDescriptor()"));
sl@0
  1268
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1269
	r = gPort.GetProductStringDescriptor(rd_str);
sl@0
  1270
	test(r == KErrNone);
sl@0
  1271
	test.Printf(_L("New Product string: \"%lS\"\n"), &rd_str);
sl@0
  1272
sl@0
  1273
	test.Next(_L("Compare Product strings"));
sl@0
  1274
	r = rd_str.Compare(wr_str);
sl@0
  1275
	test(r == KErrNone);
sl@0
  1276
sl@0
  1277
	test.Next(_L("RemoveProductStringDescriptor()"));
sl@0
  1278
	r = gPort.RemoveProductStringDescriptor();
sl@0
  1279
	test(r == KErrNone);
sl@0
  1280
	r = gPort.GetProductStringDescriptor(rd_str);
sl@0
  1281
	test(r == KErrNotFound);
sl@0
  1282
sl@0
  1283
	if (restore_string)
sl@0
  1284
		{
sl@0
  1285
		test.Next(_L("Restore original string"));
sl@0
  1286
		r = gPort.SetProductStringDescriptor(rd_str_orig);
sl@0
  1287
		test(r == KErrNone);
sl@0
  1288
		r = gPort.GetProductStringDescriptor(rd_str);
sl@0
  1289
		test(r == KErrNone);
sl@0
  1290
		r = rd_str.Compare(rd_str_orig);
sl@0
  1291
		test(r == KErrNone);
sl@0
  1292
		}
sl@0
  1293
sl@0
  1294
	//
sl@0
  1295
	// --- Serial Number string
sl@0
  1296
	//
sl@0
  1297
sl@0
  1298
	test.Next(_L("GetSerialNumberStringDescriptor()"));
sl@0
  1299
	rd_str_orig.FillZ(rd_str.MaxLength());
sl@0
  1300
	r = gPort.GetSerialNumberStringDescriptor(rd_str_orig);
sl@0
  1301
	test(r == KErrNone || r == KErrNotFound);
sl@0
  1302
	if (r == KErrNone)
sl@0
  1303
		{
sl@0
  1304
		test.Printf(_L("Old Serial Number: \"%lS\"\n"), &rd_str_orig);
sl@0
  1305
		restore_string = ETrue;
sl@0
  1306
		}
sl@0
  1307
	else
sl@0
  1308
		restore_string = EFalse;
sl@0
  1309
sl@0
  1310
	test.Next(_L("SetSerialNumberStringDescriptor()"));
sl@0
  1311
	_LIT16(serial, "000666000XYZ");
sl@0
  1312
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1313
	wr_str = serial;
sl@0
  1314
	r = gPort.SetSerialNumberStringDescriptor(wr_str);
sl@0
  1315
	test(r == KErrNone);
sl@0
  1316
sl@0
  1317
	test.Next(_L("GetSerialNumberStringDescriptor()"));
sl@0
  1318
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1319
	r = gPort.GetSerialNumberStringDescriptor(rd_str);
sl@0
  1320
	test(r == KErrNone);
sl@0
  1321
	test.Printf(_L("New Serial Number: \"%lS\"\n"), &rd_str);
sl@0
  1322
sl@0
  1323
	test.Next(_L("Compare Serial Number strings"));
sl@0
  1324
	r = rd_str.Compare(wr_str);
sl@0
  1325
	test(r == KErrNone);
sl@0
  1326
sl@0
  1327
	test.Next(_L("SetSerialNumberStringDescriptor()"));
sl@0
  1328
	_LIT16(serial2, "Y11611193111711111Y");
sl@0
  1329
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1330
	wr_str = serial2;
sl@0
  1331
	r = gPort.SetSerialNumberStringDescriptor(wr_str);
sl@0
  1332
	test(r == KErrNone);
sl@0
  1333
sl@0
  1334
	test.Next(_L("GetSerialNumberStringDescriptor()"));
sl@0
  1335
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1336
	r = gPort.GetSerialNumberStringDescriptor(rd_str);
sl@0
  1337
	test(r == KErrNone);
sl@0
  1338
	test.Printf(_L("New Serial Number: \"%lS\"\n"), &rd_str);
sl@0
  1339
sl@0
  1340
	test.Next(_L("Compare Serial Number strings"));
sl@0
  1341
	r = rd_str.Compare(wr_str);
sl@0
  1342
	test(r == KErrNone);
sl@0
  1343
sl@0
  1344
	test.Next(_L("RemoveSerialNumberStringDescriptor()"));
sl@0
  1345
	r = gPort.RemoveSerialNumberStringDescriptor();
sl@0
  1346
	test(r == KErrNone);
sl@0
  1347
	r = gPort.GetSerialNumberStringDescriptor(rd_str);
sl@0
  1348
	test(r == KErrNotFound);
sl@0
  1349
sl@0
  1350
	if (restore_string)
sl@0
  1351
		{
sl@0
  1352
		test.Next(_L("Restore original string"));
sl@0
  1353
		r = gPort.SetSerialNumberStringDescriptor(rd_str_orig);
sl@0
  1354
		test(r == KErrNone);
sl@0
  1355
		r = gPort.GetSerialNumberStringDescriptor(rd_str);
sl@0
  1356
		test(r == KErrNone);
sl@0
  1357
		r = rd_str.Compare(rd_str_orig);
sl@0
  1358
		test(r == KErrNone);
sl@0
  1359
		}
sl@0
  1360
sl@0
  1361
	//
sl@0
  1362
	// --- Configuration string
sl@0
  1363
	//
sl@0
  1364
sl@0
  1365
	test.Next(_L("GetConfigurationStringDescriptor()"));
sl@0
  1366
	rd_str_orig.FillZ(rd_str.MaxLength());
sl@0
  1367
	r = gPort.GetConfigurationStringDescriptor(rd_str_orig);
sl@0
  1368
	test(r == KErrNone || r == KErrNotFound);
sl@0
  1369
	if (r == KErrNone)
sl@0
  1370
		{
sl@0
  1371
		test.Printf(_L("Old Configuration string: \"%lS\"\n"), &rd_str_orig);
sl@0
  1372
		restore_string = ETrue;
sl@0
  1373
		}
sl@0
  1374
	else
sl@0
  1375
		restore_string = EFalse;
sl@0
  1376
sl@0
  1377
	test.Next(_L("SetConfigurationStringDescriptor()"));
sl@0
  1378
	_LIT16(config, "Relatively Simple Configuration That Is Still Useful");
sl@0
  1379
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1380
	wr_str = config;
sl@0
  1381
	r = gPort.SetConfigurationStringDescriptor(wr_str);
sl@0
  1382
	test(r == KErrNone);
sl@0
  1383
sl@0
  1384
	test.Next(_L("GetConfigurationStringDescriptor()"));
sl@0
  1385
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1386
	r = gPort.GetConfigurationStringDescriptor(rd_str);
sl@0
  1387
	test(r == KErrNone);
sl@0
  1388
	test.Printf(_L("New Configuration string: \"%lS\"\n"), &rd_str);
sl@0
  1389
sl@0
  1390
	test.Next(_L("Compare Configuration strings"));
sl@0
  1391
	r = rd_str.Compare(wr_str);
sl@0
  1392
	test(r == KErrNone);
sl@0
  1393
sl@0
  1394
	test.Next(_L("SetConfigurationStringDescriptor()"));
sl@0
  1395
	_LIT16(config2, "Convenient Configuration That Can Be Very Confusing");
sl@0
  1396
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1397
	wr_str = config2;
sl@0
  1398
	r = gPort.SetConfigurationStringDescriptor(wr_str);
sl@0
  1399
	test(r == KErrNone);
sl@0
  1400
sl@0
  1401
	test.Next(_L("GetConfigurationStringDescriptor()"));
sl@0
  1402
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1403
	r = gPort.GetConfigurationStringDescriptor(rd_str);
sl@0
  1404
	test(r == KErrNone);
sl@0
  1405
	test.Printf(_L("New Configuration string: \"%lS\"\n"), &rd_str);
sl@0
  1406
sl@0
  1407
	test.Next(_L("Compare Configuration strings"));
sl@0
  1408
	r = rd_str.Compare(wr_str);
sl@0
  1409
	test(r == KErrNone);
sl@0
  1410
sl@0
  1411
	test.Next(_L("RemoveConfigurationStringDescriptor()"));
sl@0
  1412
	r = gPort.RemoveConfigurationStringDescriptor();
sl@0
  1413
	test(r == KErrNone);
sl@0
  1414
	r = gPort.GetConfigurationStringDescriptor(rd_str);
sl@0
  1415
	test(r == KErrNotFound);
sl@0
  1416
sl@0
  1417
	if (restore_string)
sl@0
  1418
		{
sl@0
  1419
		test.Next(_L("Restore original string"));
sl@0
  1420
		r = gPort.SetConfigurationStringDescriptor(rd_str_orig);
sl@0
  1421
		test(r == KErrNone);
sl@0
  1422
		r = gPort.GetConfigurationStringDescriptor(rd_str);
sl@0
  1423
		test(r == KErrNone);
sl@0
  1424
		r = rd_str.Compare(rd_str_orig);
sl@0
  1425
		test(r == KErrNone);
sl@0
  1426
		}
sl@0
  1427
sl@0
  1428
	test.End();
sl@0
  1429
	}
sl@0
  1430
sl@0
  1431
sl@0
  1432
//---------------------------------------------
sl@0
  1433
//! @SYMTestCaseID KBASE-T_USBAPI-0041
sl@0
  1434
//! @SYMTestType UT
sl@0
  1435
//! @SYMREQ REQ5662
sl@0
  1436
//! @SYMTestCaseDesc USB Device Driver API extension to support setting of a string descriptor at a specific index
sl@0
  1437
//! @SYMTestActions Tests GetStringDescriptor(), SetStringDescriptor() and RemoveStringDescriptor() to verify
sl@0
  1438
//! the right values are retrieved, set and deleted at specific positions
sl@0
  1439
//! @SYMTestExpectedResults KErrNone in positive testing and KErrNotFound in negative one
sl@0
  1440
//! @SYMTestPriority High
sl@0
  1441
//! @SYMTestStatus Implemented
sl@0
  1442
//---------------------------------------------
sl@0
  1443
static void TestArbitraryStringDescriptors()
sl@0
  1444
	{
sl@0
  1445
	test.Start(_L("Arbitrary String Descriptor Manipulation"));
sl@0
  1446
sl@0
  1447
	const TUint8 stridx1 = 0xEE;
sl@0
  1448
	const TUint8 stridx2 = 0xCC;
sl@0
  1449
	const TUint8 stridx3 = 0xDD;
sl@0
  1450
	const TUint8 stridx4 = 0xFF;
sl@0
  1451
sl@0
  1452
	// First test string
sl@0
  1453
sl@0
  1454
	test.Next(_L("GetStringDescriptor() 1"));
sl@0
  1455
	TBuf16<KUsbStringDescStringMaxSize / 2> rd_str;
sl@0
  1456
	TInt r = gPort.GetStringDescriptor(stridx1, rd_str);
sl@0
  1457
	test(r == KErrNotFound);
sl@0
  1458
sl@0
  1459
	test.Next(_L("SetStringDescriptor() 1"));
sl@0
  1460
	_LIT16(string_one, "Arbitrary String Descriptor Test String 1");
sl@0
  1461
	TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(string_one);
sl@0
  1462
	r = gPort.SetStringDescriptor(stridx1, wr_str);
sl@0
  1463
	test(r == KErrNone);
sl@0
  1464
sl@0
  1465
	test.Next(_L("GetStringDescriptor() 1"));
sl@0
  1466
	r = gPort.GetStringDescriptor(stridx1, rd_str);
sl@0
  1467
	test(r == KErrNone);
sl@0
  1468
	test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx1, &rd_str);
sl@0
  1469
sl@0
  1470
	test.Next(_L("Compare test strings 1"));
sl@0
  1471
	r = rd_str.Compare(wr_str);
sl@0
  1472
	test(r == KErrNone);
sl@0
  1473
sl@0
  1474
	// Second test string
sl@0
  1475
sl@0
  1476
	test.Next(_L("GetStringDescriptor() 2"));
sl@0
  1477
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1478
	r = gPort.GetStringDescriptor(stridx2, rd_str);
sl@0
  1479
	test(r == KErrNotFound);
sl@0
  1480
sl@0
  1481
	test.Next(_L("SetStringDescriptor() 2"));
sl@0
  1482
	_LIT16(string_two, "Arbitrary String Descriptor Test String 2");
sl@0
  1483
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1484
	wr_str = string_two;
sl@0
  1485
	r = gPort.SetStringDescriptor(stridx2, wr_str);
sl@0
  1486
	test(r == KErrNone);
sl@0
  1487
sl@0
  1488
	// In between we create another interface setting to see what happens
sl@0
  1489
	// to the existing string descriptor indices.
sl@0
  1490
	// (We don't have to test this on every platform -
sl@0
  1491
	// besides, those that don't support alt settings
sl@0
  1492
	// are by now very rare.)
sl@0
  1493
	if (SupportsAlternateInterfaces())
sl@0
  1494
		{
sl@0
  1495
		TUsbcInterfaceInfoBuf ifc;
sl@0
  1496
		_LIT16(string, "T_USBAPI Bogus Test Interface (Setting 2)");
sl@0
  1497
		ifc().iString = const_cast<TDesC16*>(&string);
sl@0
  1498
		ifc().iTotalEndpointsUsed = 0;
sl@0
  1499
		TInt r = gPort.SetInterface(2, ifc);
sl@0
  1500
		test(r == KErrNone);
sl@0
  1501
		}
sl@0
  1502
sl@0
  1503
	test.Next(_L("GetStringDescriptor() 2"));
sl@0
  1504
	r = gPort.GetStringDescriptor(stridx2, rd_str);
sl@0
  1505
	test(r == KErrNone);
sl@0
  1506
	test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx2, &rd_str);
sl@0
  1507
sl@0
  1508
	test.Next(_L("Compare test strings 2"));
sl@0
  1509
	r = rd_str.Compare(wr_str);
sl@0
  1510
	test(r == KErrNone);
sl@0
  1511
sl@0
  1512
	// Third test string
sl@0
  1513
sl@0
  1514
	test.Next(_L("GetStringDescriptor() 3"));
sl@0
  1515
	rd_str.FillZ(rd_str.MaxLength());
sl@0
  1516
	r = gPort.GetStringDescriptor(stridx3, rd_str);
sl@0
  1517
	test(r == KErrNotFound);
sl@0
  1518
sl@0
  1519
	test.Next(_L("SetStringDescriptor() 3"));
sl@0
  1520
	_LIT16(string_three, "Arbitrary String Descriptor Test String 3");
sl@0
  1521
	wr_str.FillZ(wr_str.MaxLength());
sl@0
  1522
	wr_str = string_three;
sl@0
  1523
	r = gPort.SetStringDescriptor(stridx3, wr_str);
sl@0
  1524
	test(r == KErrNone);
sl@0
  1525
sl@0
  1526
	test.Next(_L("GetStringDescriptor() 3"));
sl@0
  1527
	r = gPort.GetStringDescriptor(stridx3, rd_str);
sl@0
  1528
	test(r == KErrNone);
sl@0
  1529
	test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx3, &rd_str);
sl@0
  1530
sl@0
  1531
	test.Next(_L("Compare test strings 3"));
sl@0
  1532
	r = rd_str.Compare(wr_str);
sl@0
  1533
	test(r == KErrNone);
sl@0
  1534
sl@0
  1535
	// Remove string descriptors
sl@0
  1536
sl@0
  1537
	test.Next(_L("RemoveStringDescriptor() 4"));
sl@0
  1538
	r = gPort.RemoveStringDescriptor(stridx4);
sl@0
  1539
	test(r == KErrNotFound);
sl@0
  1540
sl@0
  1541
	test.Next(_L("RemoveStringDescriptor() 3"));
sl@0
  1542
	r = gPort.RemoveStringDescriptor(stridx3);
sl@0
  1543
	test(r == KErrNone);
sl@0
  1544
	r = gPort.GetStringDescriptor(stridx3, rd_str);
sl@0
  1545
	test(r == KErrNotFound);
sl@0
  1546
sl@0
  1547
	test.Next(_L("RemoveStringDescriptor() 2"));
sl@0
  1548
	r = gPort.RemoveStringDescriptor(stridx2);
sl@0
  1549
	test(r == KErrNone);
sl@0
  1550
	r = gPort.GetStringDescriptor(stridx2, rd_str);
sl@0
  1551
	test(r == KErrNotFound);
sl@0
  1552
sl@0
  1553
	test.Next(_L("RemoveStringDescriptor() 1"));
sl@0
  1554
	r = gPort.RemoveStringDescriptor(stridx1);
sl@0
  1555
	test(r == KErrNone);
sl@0
  1556
	r = gPort.GetStringDescriptor(stridx1, rd_str);
sl@0
  1557
	test(r == KErrNotFound);
sl@0
  1558
sl@0
  1559
	test.End();
sl@0
  1560
	}
sl@0
  1561
sl@0
  1562
sl@0
  1563
static void TestDescriptorManipulation()
sl@0
  1564
	{
sl@0
  1565
	test.Start(_L("Test USB Descriptor Manipulation"));
sl@0
  1566
sl@0
  1567
	TestDeviceDescriptor();
sl@0
  1568
sl@0
  1569
	TestDeviceQualifierDescriptor();
sl@0
  1570
sl@0
  1571
	TestConfigurationDescriptor();
sl@0
  1572
sl@0
  1573
	TestOtherSpeedConfigurationDescriptor();
sl@0
  1574
sl@0
  1575
	TestInterfaceDescriptor();
sl@0
  1576
sl@0
  1577
	TestClassSpecificDescriptors();
sl@0
  1578
sl@0
  1579
	TestAlternateInterfaceManipulation();
sl@0
  1580
sl@0
  1581
	TestEndpointDescriptor();
sl@0
  1582
sl@0
  1583
	TestExtendedEndpointDescriptor();
sl@0
  1584
sl@0
  1585
	TestStandardStringDescriptors();
sl@0
  1586
sl@0
  1587
	TestArbitraryStringDescriptors();
sl@0
  1588
sl@0
  1589
	test.End();
sl@0
  1590
	}
sl@0
  1591
sl@0
  1592
sl@0
  1593
//---------------------------------------------
sl@0
  1594
//! @SYMTestCaseID KBASE-T_USBAPI-0040
sl@0
  1595
//! @SYMTestType UT
sl@0
  1596
//! @SYMTestCaseDesc Test OTG extensions
sl@0
  1597
//! @SYMTestExpectedResults All APIs behave as expected
sl@0
  1598
//! @SYMTestPriority Medium
sl@0
  1599
//! @SYMTestStatus Implemented
sl@0
  1600
//---------------------------------------------
sl@0
  1601
static void TestOtgExtensions()
sl@0
  1602
	{
sl@0
  1603
	test.Start(_L("Test Some OTG API Extensions"));
sl@0
  1604
sl@0
  1605
	// Test OTG descriptor manipulation
sl@0
  1606
	test.Next(_L("Get OTG Descriptor Size"));
sl@0
  1607
	TInt size;
sl@0
  1608
	gPort.GetOtgDescriptorSize(size);
sl@0
  1609
	test(static_cast<TUint>(size) == KUsbDescSize_Otg);
sl@0
  1610
sl@0
  1611
	test.Next(_L("Get OTG Descriptor"));
sl@0
  1612
	TBuf8<KUsbDescSize_Otg> otgDesc;
sl@0
  1613
	TInt r = gPort.GetOtgDescriptor(otgDesc);
sl@0
  1614
	test(r == KErrNotSupported || r == KErrNone);
sl@0
  1615
sl@0
  1616
	test.Next(_L("Set OTG Descriptor"));
sl@0
  1617
	if (r == KErrNotSupported)
sl@0
  1618
		{
sl@0
  1619
		r = gPort.SetOtgDescriptor(otgDesc);
sl@0
  1620
		test(r == KErrNotSupported);
sl@0
  1621
		}
sl@0
  1622
	else
sl@0
  1623
		{
sl@0
  1624
		otgDesc[0] = KUsbDescSize_Otg;
sl@0
  1625
		otgDesc[1] = KUsbDescType_Otg;
sl@0
  1626
		// The next step is likely to reset KUsbOtgAttr_HnpSupp
sl@0
  1627
		otgDesc[2] = KUsbOtgAttr_SrpSupp;
sl@0
  1628
		r = gPort.SetOtgDescriptor(otgDesc);
sl@0
  1629
		test(r == KErrNone);
sl@0
  1630
		TBuf8<KUsbDescSize_Otg> desc;
sl@0
  1631
		r = gPort.GetOtgDescriptor(desc);
sl@0
  1632
		test(r == KErrNone);
sl@0
  1633
		test(desc.Compare(otgDesc) == 0);
sl@0
  1634
		}
sl@0
  1635
sl@0
  1636
	// Test get OTG features
sl@0
  1637
	test.Next(_L("Get OTG Features"));
sl@0
  1638
	TUint8 features;
sl@0
  1639
	r = gPort.GetOtgFeatures(features);
sl@0
  1640
	if (gSupportsOtg)
sl@0
  1641
		{
sl@0
  1642
		test(r == KErrNone);
sl@0
  1643
		TBool b_HnpEnable = (features & KUsbOtgAttr_B_HnpEnable) ? ETrue : EFalse;
sl@0
  1644
		TBool a_HnpSupport = (features & KUsbOtgAttr_A_HnpSupport) ? ETrue : EFalse;
sl@0
  1645
		TBool a_AltHnpSupport = (features & KUsbOtgAttr_A_AltHnpSupport) ? ETrue : EFalse;
sl@0
  1646
		test.Printf(_L("### OTG Features:\nB_HnpEnable(%d)\nA_HnpSupport(%d)\nA_Alt_HnpSupport(%d)\n"),
sl@0
  1647
					b_HnpEnable, a_HnpSupport, a_AltHnpSupport);
sl@0
  1648
		}
sl@0
  1649
	else
sl@0
  1650
		{
sl@0
  1651
		test(r == KErrNotSupported);
sl@0
  1652
		test.Printf(_L("GetOtgFeatures() not supported\n"));
sl@0
  1653
		}
sl@0
  1654
sl@0
  1655
	test.End();
sl@0
  1656
}
sl@0
  1657
sl@0
  1658
sl@0
  1659
static void TestEndpoint0MaxPacketSizes()
sl@0
  1660
	{
sl@0
  1661
	test.Start(_L("Test Endpoint0 MaxPacketSizes"));
sl@0
  1662
sl@0
  1663
	TUint32 sizes = gPort.EndpointZeroMaxPacketSizes();
sl@0
  1664
	TInt r = KErrNone;
sl@0
  1665
	TBool good;
sl@0
  1666
	TInt mpsize = 0;
sl@0
  1667
	for (TInt i = 0; i < 32; i++)
sl@0
  1668
		{
sl@0
  1669
		TUint bit = sizes & (1 << i);
sl@0
  1670
		if (bit != 0)
sl@0
  1671
			{
sl@0
  1672
			switch (bit)
sl@0
  1673
				{
sl@0
  1674
			case KUsbEpSizeCont:
sl@0
  1675
				good = EFalse;
sl@0
  1676
				break;
sl@0
  1677
			case KUsbEpSize8:
sl@0
  1678
				mpsize = 8;
sl@0
  1679
				good = ETrue;
sl@0
  1680
				break;
sl@0
  1681
			case KUsbEpSize16:
sl@0
  1682
				mpsize = 16;
sl@0
  1683
				good = ETrue;
sl@0
  1684
				break;
sl@0
  1685
			case KUsbEpSize32:
sl@0
  1686
				mpsize = 32;
sl@0
  1687
				good = ETrue;
sl@0
  1688
				break;
sl@0
  1689
			case KUsbEpSize64:
sl@0
  1690
				mpsize = 64;
sl@0
  1691
				good = ETrue;
sl@0
  1692
				break;
sl@0
  1693
			case KUsbEpSize128:
sl@0
  1694
			case KUsbEpSize256:
sl@0
  1695
			case KUsbEpSize512:
sl@0
  1696
			case KUsbEpSize1023:
sl@0
  1697
			default:
sl@0
  1698
				good = EFalse;
sl@0
  1699
				break;
sl@0
  1700
				}
sl@0
  1701
			if (good)
sl@0
  1702
				{
sl@0
  1703
				test.Printf(_L("Ep0 supports %d bytes MaxPacketSize\n"), mpsize);
sl@0
  1704
				}
sl@0
  1705
			else
sl@0
  1706
				{
sl@0
  1707
				test.Printf(_L("Bad Ep0 size: 0x%08x, failure will occur\n"), bit);
sl@0
  1708
				r = KErrGeneral;
sl@0
  1709
				}
sl@0
  1710
			}
sl@0
  1711
		}
sl@0
  1712
	test(r == KErrNone);
sl@0
  1713
sl@0
  1714
    test.End();
sl@0
  1715
	}
sl@0
  1716
sl@0
  1717
sl@0
  1718
static void TestDeviceControl()
sl@0
  1719
	{
sl@0
  1720
	test.Start(_L("Test Device Control"));
sl@0
  1721
sl@0
  1722
	// This is a quick and crude test, to make sure that we don't get a steaming heap
sl@0
  1723
	// as a result of calling the device control API's.
sl@0
  1724
	test.Next(_L("SetDeviceControl()"));
sl@0
  1725
	TInt r = gPort.SetDeviceControl();
sl@0
  1726
	test(r == KErrNone);
sl@0
  1727
	test.Next(_L("ReleaseDeviceControl()"));
sl@0
  1728
	r = gPort.ReleaseDeviceControl();
sl@0
  1729
	test(r == KErrNone);
sl@0
  1730
sl@0
  1731
	test.End();
sl@0
  1732
	}
sl@0
  1733
sl@0
  1734
sl@0
  1735
static void TestAlternateDeviceStatusNotify()
sl@0
  1736
	{
sl@0
  1737
	test.Start(_L("Test Alternate Device Status Notification"));
sl@0
  1738
sl@0
  1739
	TRequestStatus dev_status;
sl@0
  1740
	TUint deviceState = 0xffffffff;						// put in a nonsense value
sl@0
  1741
	test.Next(_L("AlternateDeviceStatusNotify()"));
sl@0
  1742
	gPort.AlternateDeviceStatusNotify(dev_status, deviceState);
sl@0
  1743
	test.Next(_L("AlternateDeviceStatusNotifyCancel()"));
sl@0
  1744
	gPort.AlternateDeviceStatusNotifyCancel();
sl@0
  1745
	User::WaitForRequest(dev_status);
sl@0
  1746
	test(dev_status == KErrCancel || dev_status == KErrNone);
sl@0
  1747
	if (deviceState & KUsbAlternateSetting)
sl@0
  1748
		{
sl@0
  1749
		TUint setting = (deviceState & ~KUsbAlternateSetting);
sl@0
  1750
		test.Printf(_L("Alternate setting change to setting %d - unexpected"), setting);
sl@0
  1751
		test(EFalse);
sl@0
  1752
		}
sl@0
  1753
	else
sl@0
  1754
		{
sl@0
  1755
		switch (deviceState)
sl@0
  1756
			{
sl@0
  1757
		case EUsbcDeviceStateUndefined:
sl@0
  1758
			test.Printf(_L("TestAlternateDeviceStatusNotify: Undefined state\n"));
sl@0
  1759
			break;
sl@0
  1760
		case EUsbcDeviceStateAttached:
sl@0
  1761
			test.Printf(_L("TestAlternateDeviceStatusNotify: Attached state\n"));
sl@0
  1762
			break;
sl@0
  1763
		case EUsbcDeviceStatePowered:
sl@0
  1764
			test.Printf(_L("TestAlternateDeviceStatusNotify: Powered state\n"));
sl@0
  1765
			break;
sl@0
  1766
		case EUsbcDeviceStateDefault:
sl@0
  1767
			test.Printf(_L("TestAlternateDeviceStatusNotify: Default state\n"));
sl@0
  1768
			break;
sl@0
  1769
		case EUsbcDeviceStateAddress:
sl@0
  1770
			test.Printf(_L("TestAlternateDeviceStatusNotify: Address state\n"));
sl@0
  1771
			break;
sl@0
  1772
		case EUsbcDeviceStateConfigured:
sl@0
  1773
			test.Printf(_L("TestAlternateDeviceStatusNotify: Configured state\n"));
sl@0
  1774
			break;
sl@0
  1775
		case EUsbcDeviceStateSuspended:
sl@0
  1776
			test.Printf(_L("TestAlternateDeviceStatusNotify: Suspended state\n"));
sl@0
  1777
			break;
sl@0
  1778
		case EUsbcNoState:
sl@0
  1779
			test.Printf(_L("TestAlternateDeviceStatusNotify: State buffering error\n"));
sl@0
  1780
			test(EFalse);
sl@0
  1781
			break;
sl@0
  1782
		default:
sl@0
  1783
			test.Printf(_L("TestAlternateDeviceStatusNotify: Unknown state\n"));
sl@0
  1784
			test(EFalse);
sl@0
  1785
			}
sl@0
  1786
		}
sl@0
  1787
sl@0
  1788
	test.End();
sl@0
  1789
	}
sl@0
  1790
sl@0
  1791
sl@0
  1792
static void TestEndpointStatusNotify()
sl@0
  1793
	{
sl@0
  1794
	test.Start(_L("Test Endpoint Status Notification"));
sl@0
  1795
sl@0
  1796
	TRequestStatus ep_status;
sl@0
  1797
	TUint epStateBitmap = 0xffffffff;						// put in a nonsense value
sl@0
  1798
	test.Next(_L("EndpointStatusNotify()"));
sl@0
  1799
	gPort.EndpointStatusNotify(ep_status, epStateBitmap);
sl@0
  1800
	test.Next(_L("EndpointStatusNotifyCancel()"));
sl@0
  1801
	gPort.EndpointStatusNotifyCancel();
sl@0
  1802
	User::WaitForRequest(ep_status);
sl@0
  1803
	test(ep_status.Int() == KErrCancel);
sl@0
  1804
	test.Next(_L("Check endpoint state bitmap returned"));
sl@0
  1805
	// Our ifc only uses 2 eps + ep0 is automatically granted:
sl@0
  1806
	const TUint usedEpBitmap = (1 << EEndpoint0 | 1 << EEndpoint1 | 1 << EEndpoint2);
sl@0
  1807
	// Must not return info about non existent Eps:
sl@0
  1808
	test((epStateBitmap & ~usedEpBitmap) == 0);
sl@0
  1809
	for (TInt i = 0; i <= 2; i++)
sl@0
  1810
		{
sl@0
  1811
		if ((epStateBitmap & (1 << i)) == EEndpointStateNotStalled)
sl@0
  1812
			{
sl@0
  1813
			test.Printf(_L("EndpointStatusNotify: Ep %d NOT STALLED\n"), i);
sl@0
  1814
			}
sl@0
  1815
		else
sl@0
  1816
			{
sl@0
  1817
			test.Printf(_L("EndpointStatusNotify: Ep %d STALLED\n"), i);
sl@0
  1818
			}
sl@0
  1819
		}
sl@0
  1820
sl@0
  1821
	test.End();
sl@0
  1822
	}
sl@0
  1823
sl@0
  1824
sl@0
  1825
static void TestEndpointStallStatus()
sl@0
  1826
	{
sl@0
  1827
	test.Start(_L("Test Endpoint Stall Status"));
sl@0
  1828
sl@0
  1829
	if (!SupportsEndpointStall())
sl@0
  1830
		{
sl@0
  1831
		test.Printf(_L("*** Not supported - skipping endpoint stall status tests\n"));
sl@0
  1832
		test.End();
sl@0
  1833
		return;
sl@0
  1834
		}
sl@0
  1835
sl@0
  1836
	test.Next(_L("Endpoint stall status"));
sl@0
  1837
	TEndpointState epState = EEndpointStateUnknown;
sl@0
  1838
	QueryEndpointState(EEndpoint1);
sl@0
  1839
	QueryEndpointState(EEndpoint2);
sl@0
  1840
sl@0
  1841
	test.Next(_L("Stall Ep1"));
sl@0
  1842
	gPort.HaltEndpoint(EEndpoint1);
sl@0
  1843
	epState = QueryEndpointState(EEndpoint1);
sl@0
  1844
	test(epState == EEndpointStateStalled);
sl@0
  1845
sl@0
  1846
	test.Next(_L("Clear Stall Ep1"));
sl@0
  1847
	gPort.ClearHaltEndpoint(EEndpoint1);
sl@0
  1848
	epState = QueryEndpointState(EEndpoint1);
sl@0
  1849
	test(epState == EEndpointStateNotStalled);
sl@0
  1850
sl@0
  1851
	test.Next(_L("Stall Ep2"));
sl@0
  1852
	gPort.HaltEndpoint(EEndpoint2);
sl@0
  1853
	epState = QueryEndpointState(EEndpoint2);
sl@0
  1854
	test(epState == EEndpointStateStalled);
sl@0
  1855
sl@0
  1856
	test.Next(_L("Clear Stall Ep2"));
sl@0
  1857
	gPort.ClearHaltEndpoint(EEndpoint2);
sl@0
  1858
	epState = QueryEndpointState(EEndpoint2);
sl@0
  1859
	test(epState == EEndpointStateNotStalled);
sl@0
  1860
sl@0
  1861
	test.End();
sl@0
  1862
	}
sl@0
  1863
sl@0
  1864
sl@0
  1865
static void CloseChannel()
sl@0
  1866
	{
sl@0
  1867
	test.Start(_L("Close Channel"));
sl@0
  1868
sl@0
  1869
	test.Next(_L("Disconnect Device from Host"));
sl@0
  1870
	TInt r = gPort.DeviceDisconnectFromHost();
sl@0
  1871
	test(r != KErrGeneral);
sl@0
  1872
sl@0
  1873
	if (gSupportsOtg)
sl@0
  1874
		{
sl@0
  1875
		test.Next(_L("Stop OTG stack"));
sl@0
  1876
		gOTG.StopStacks();
sl@0
  1877
		test.Next(_L("Close OTG Channel"));
sl@0
  1878
		gOTG.Close();
sl@0
  1879
		test.Next(_L("Free OTG LDD"));
sl@0
  1880
		r = User::FreeLogicalDevice(RUsbOtgDriver::Name());
sl@0
  1881
		test(r == KErrNone);
sl@0
  1882
		}
sl@0
  1883
sl@0
  1884
	test.Next(_L("Close USB Channel"));
sl@0
  1885
	gPort.Close();
sl@0
  1886
	test.Next(_L("Free USB LDD"));
sl@0
  1887
	r = User::FreeLogicalDevice(KUsbDeviceName);
sl@0
  1888
	test(r == KErrNone);
sl@0
  1889
sl@0
  1890
	test.End();
sl@0
  1891
	}
sl@0
  1892
sl@0
  1893
sl@0
  1894
static const TInt KPrologue = 0;
sl@0
  1895
static const TInt KMain     = 1;
sl@0
  1896
static const TInt KEpilogue = 2;
sl@0
  1897
sl@0
  1898
static TInt RunTests(void* /*aArg*/)
sl@0
  1899
	{
sl@0
  1900
	static TInt step = KPrologue;
sl@0
  1901
	static TReal loops = 0;
sl@0
  1902
sl@0
  1903
	switch (step)
sl@0
  1904
		{
sl@0
  1905
	case KPrologue:
sl@0
  1906
		test.Title();
sl@0
  1907
		// outermost test begin
sl@0
  1908
		test.Start(_L("Test of USB APIs not requiring a host connection\n"));
sl@0
  1909
		if (SupportsUsb())
sl@0
  1910
			{
sl@0
  1911
			step = KMain;
sl@0
  1912
			}
sl@0
  1913
		else
sl@0
  1914
			{
sl@0
  1915
			step = KEpilogue;
sl@0
  1916
			test.Printf(_L("*** Test platform does not support USB - skipping all tests\n"));
sl@0
  1917
			}
sl@0
  1918
		return ETrue;
sl@0
  1919
	case KMain:
sl@0
  1920
		OpenChannel();
sl@0
  1921
		SetupInterface();
sl@0
  1922
		TestDescriptorManipulation();
sl@0
  1923
		TestOtgExtensions();
sl@0
  1924
		TestEndpoint0MaxPacketSizes();
sl@0
  1925
		TestDeviceControl();
sl@0
  1926
		TestAlternateDeviceStatusNotify();
sl@0
  1927
		TestEndpointStatusNotify();
sl@0
  1928
		TestEndpointStallStatus();
sl@0
  1929
		CloseChannel();
sl@0
  1930
		loops++;
sl@0
  1931
		if (gSoak && (gKeychar != EKeyEscape))
sl@0
  1932
			{
sl@0
  1933
			step = KMain;
sl@0
  1934
			}
sl@0
  1935
		else
sl@0
  1936
			{
sl@0
  1937
			step = KEpilogue;
sl@0
  1938
			}
sl@0
  1939
		return ETrue;
sl@0
  1940
	case KEpilogue:
sl@0
  1941
		test.Printf(_L("USBAPI tests were run %.0f time(s)\n"), loops);
sl@0
  1942
		// outermost test end
sl@0
  1943
		test.End();
sl@0
  1944
		CActiveScheduler::Stop();
sl@0
  1945
		return EFalse;
sl@0
  1946
		}
sl@0
  1947
	return EFalse;
sl@0
  1948
	}
sl@0
  1949
sl@0
  1950
sl@0
  1951
static void RunAppL()
sl@0
  1952
	{
sl@0
  1953
	// Create the active scheduler
sl@0
  1954
	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
sl@0
  1955
	// Push active scheduler onto the cleanup stack
sl@0
  1956
	CleanupStack::PushL(scheduler);
sl@0
  1957
	// Install as the active scheduler
sl@0
  1958
	CActiveScheduler::Install(scheduler);
sl@0
  1959
sl@0
  1960
	// Create console handler
sl@0
  1961
	CConsoleBase* console =
sl@0
  1962
		Console::NewL(_L("T_USBAPI - USB Client Test Program"), TSize(KConsFullScreen, KConsFullScreen));
sl@0
  1963
	CleanupStack::PushL(console);
sl@0
  1964
	// Make this one also RTest's console
sl@0
  1965
	test.SetConsole(console);
sl@0
  1966
sl@0
  1967
	// Create keypress notifier active object
sl@0
  1968
	CActiveKeypressNotifier* keypress_notifier = CActiveKeypressNotifier::NewL(console);
sl@0
  1969
	test(keypress_notifier != NULL);
sl@0
  1970
	CleanupStack::PushL(keypress_notifier);
sl@0
  1971
	keypress_notifier->RequestCharacter();
sl@0
  1972
sl@0
  1973
	// Create long-running test task active object
sl@0
  1974
	CIdle* active_test = CIdle::NewL(CActive::EPriorityIdle);
sl@0
  1975
	test(active_test != NULL);
sl@0
  1976
	CleanupStack::PushL(active_test);
sl@0
  1977
	active_test->Start(TCallBack(RunTests));
sl@0
  1978
sl@0
  1979
	// Start active scheduler
sl@0
  1980
	CActiveScheduler::Start();
sl@0
  1981
sl@0
  1982
	// Suspend thread for a short while
sl@0
  1983
	User::After(1000000);
sl@0
  1984
sl@0
  1985
	// active_test, keypress_notifier, console, scheduler
sl@0
  1986
	CleanupStack::PopAndDestroy(4);
sl@0
  1987
sl@0
  1988
	return;
sl@0
  1989
	}
sl@0
  1990
sl@0
  1991
sl@0
  1992
GLDEF_C TInt E32Main()
sl@0
  1993
	{
sl@0
  1994
sl@0
  1995
	CTrapCleanup* cleanup = CTrapCleanup::New();			// get clean-up stack
sl@0
  1996
sl@0
  1997
	__UHEAP_MARK;
sl@0
  1998
sl@0
  1999
	_LIT(KArg, "soak");
sl@0
  2000
	TBuf<64> c;
sl@0
  2001
	User::CommandLine(c);
sl@0
  2002
	if (c.CompareF(KArg) == 0)
sl@0
  2003
		gSoak = ETrue;
sl@0
  2004
	else
sl@0
  2005
		gSoak = EFalse;
sl@0
  2006
	TRAPD(r, RunAppL());
sl@0
  2007
	__ASSERT_ALWAYS(!r, User::Panic(_L("E32EX"), r));
sl@0
  2008
sl@0
  2009
	__UHEAP_MARKEND;
sl@0
  2010
sl@0
  2011
	delete cleanup;											// destroy clean-up stack
sl@0
  2012
	return KErrNone;
sl@0
  2013
	}