os/kernelhwsrv/kerneltest/e32utils/testusbcldd/src/misc.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2004-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
// f32test\testusbcldd\src\misc.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "dtestusblogdev.h"
sl@0
    19
sl@0
    20
TUsbcInterface::TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting)
sl@0
    21
	: iEndpoints(2), iInterfaceSet(aIfcSet), iSettingCode(aSetting)
sl@0
    22
	{
sl@0
    23
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::TUsbcInterface()")));
sl@0
    24
	}
sl@0
    25
sl@0
    26
sl@0
    27
TUsbcInterface::~TUsbcInterface()
sl@0
    28
	{
sl@0
    29
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::~TUsbcInterface()")));
sl@0
    30
	iEndpoints.ResetAndDestroy();
sl@0
    31
	}
sl@0
    32
sl@0
    33
sl@0
    34
TUsbcInterfaceSet::TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum)
sl@0
    35
	: iInterfaces(2), iClientId(aClientId), iInterfaceNumber(aIfcNum), iCurrentInterface(0)
sl@0
    36
	{
sl@0
    37
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::TUsbcInterfaceSet()")));
sl@0
    38
	}
sl@0
    39
sl@0
    40
sl@0
    41
TUsbcInterfaceSet::~TUsbcInterfaceSet()
sl@0
    42
	{
sl@0
    43
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::~TUsbcInterfaceSet()")));
sl@0
    44
	iInterfaces.ResetAndDestroy();
sl@0
    45
	}
sl@0
    46
	
sl@0
    47
const TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() const
sl@0
    48
/** Returns a pointer to the currently selected (active) setting of this interface.
sl@0
    49
sl@0
    50
	@return A pointer to the currently selected (active) setting of this interface.
sl@0
    51
*/
sl@0
    52
	{
sl@0
    53
	return iInterfaces[iCurrentInterface];
sl@0
    54
	}
sl@0
    55
sl@0
    56
sl@0
    57
TUsbcInterface* TUsbcInterfaceSet::CurrentInterface()
sl@0
    58
/** Returns a pointer to the currently selected (active) setting of this interface.
sl@0
    59
sl@0
    60
	@return A pointer to the currently selected (active) setting of this interface.
sl@0
    61
*/
sl@0
    62
	{
sl@0
    63
	return iInterfaces[iCurrentInterface];
sl@0
    64
	}
sl@0
    65
sl@0
    66
TUsbcLogicalEndpoint::TUsbcLogicalEndpoint(TUint aEndpointNum, const TUsbcEndpointInfo& aInfo,
sl@0
    67
										   TUsbcInterface* aInterface)
sl@0
    68
	: iLEndpointNum(aEndpointNum), iInfo(aInfo), iInterface(aInterface)
sl@0
    69
	{
sl@0
    70
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::TUsbcLogicalEndpoint()")));
sl@0
    71
	}
sl@0
    72
sl@0
    73
sl@0
    74
TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint()
sl@0
    75
	{
sl@0
    76
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint: #%d"), iLEndpointNum));
sl@0
    77
	}
sl@0
    78
sl@0
    79
DTestUsbcEndpoint::DTestUsbcEndpoint()
sl@0
    80
	{
sl@0
    81
	}
sl@0
    82
	
sl@0
    83
DTestUsbcEndpoint::~DTestUsbcEndpoint()
sl@0
    84
	{
sl@0
    85
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Deleting buffer 0x%x"), iBuffer));
sl@0
    86
	delete iBuffer;
sl@0
    87
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Buffer deleted")));
sl@0
    88
	}
sl@0
    89
	
sl@0
    90
TInt DTestUsbcEndpoint::Create(const TUsbcEndpointCaps& aCaps)
sl@0
    91
	{
sl@0
    92
	iCaps = aCaps;
sl@0
    93
	if (iBuffer == NULL)
sl@0
    94
		{
sl@0
    95
		__NEWPLATBUF(iBuffer, KEndpointBufferSize);
sl@0
    96
		if (iBuffer == NULL)
sl@0
    97
			return KErrNoMemory;
sl@0
    98
		}
sl@0
    99
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Allocated buffer 0x%x"), iBuffer));
sl@0
   100
	return KErrNone;
sl@0
   101
	}
sl@0
   102
sl@0
   103
void DTestUsbcEndpoint::DoCancel()
sl@0
   104
	{
sl@0
   105
	if (iRequestPending)
sl@0
   106
		{
sl@0
   107
		//Cancel client request
sl@0
   108
		iRequestPending = EFalse;
sl@0
   109
		Kern::RequestComplete(iClient, iClientStatus, KErrCancel);
sl@0
   110
		}
sl@0
   111
	if (iHostRequestPending)
sl@0
   112
		{
sl@0
   113
		//Cancel host request
sl@0
   114
		iHostRequestPending = EFalse;
sl@0
   115
		Kern::RequestComplete(iHost, iHostStatus, KErrCancel);
sl@0
   116
		}
sl@0
   117
	}
sl@0
   118
sl@0
   119
TInt DTestUsbcEndpoint::NewRequest(DThread* aClient, TRequestStatus* aStatus, 
sl@0
   120
								   TEndpointTransferInfo& aInfo, TTransferType aType)
sl@0
   121
	{
sl@0
   122
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewRequest")));
sl@0
   123
	//Only supports one request pending per endpoint
sl@0
   124
	if (iRequestPending)
sl@0
   125
		{
sl@0
   126
		return ERequestAlreadyPending;
sl@0
   127
		}
sl@0
   128
	iClient = aClient;
sl@0
   129
	iClientStatus = aStatus;
sl@0
   130
	iClientTransferInfo = aInfo;
sl@0
   131
	iDataTransferred = 0;
sl@0
   132
	iRequestPending = ETrue;
sl@0
   133
	iRequestType = aType;
sl@0
   134
	
sl@0
   135
	//Copy data to local buffer if this is a write request
sl@0
   136
	if (iRequestType == ETransferTypeWrite)
sl@0
   137
		{
sl@0
   138
		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request")));
sl@0
   139
		TInt err;		
sl@0
   140
		__THREADREADPLATBUF(aClient, iClientTransferInfo.iDes, iBuffer, err);
sl@0
   141
		if (err != KErrNone)
sl@0
   142
			{
sl@0
   143
			iRequestPending = EFalse;
sl@0
   144
			return err;
sl@0
   145
			}
sl@0
   146
		}
sl@0
   147
	else
sl@0
   148
		{
sl@0
   149
		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request")));
sl@0
   150
		}
sl@0
   151
	
sl@0
   152
	if (iHostRequestPending)
sl@0
   153
		{
sl@0
   154
		TryToComplete();
sl@0
   155
		}
sl@0
   156
	
sl@0
   157
	return KErrNone;
sl@0
   158
	}
sl@0
   159
sl@0
   160
TInt DTestUsbcEndpoint::NewHostRequest(DThread* aHost, TRequestStatus* aStatus,
sl@0
   161
									   TEndpointTransferInfo& aInfo, TTransferType aType)
sl@0
   162
	{
sl@0
   163
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewHostRequest")));
sl@0
   164
	//Only supports one request pending per endpoint
sl@0
   165
	if (iHostRequestPending)
sl@0
   166
		{
sl@0
   167
		return ERequestAlreadyPending;
sl@0
   168
		}
sl@0
   169
	iHost = aHost;
sl@0
   170
	iHostStatus = aStatus;
sl@0
   171
	iHostTransferInfo = aInfo;
sl@0
   172
	iHostDataTransferred = 0;
sl@0
   173
	iHostRequestPending = ETrue;
sl@0
   174
	iHostRequestType = aType;
sl@0
   175
	
sl@0
   176
	//Copy data to local buffer if this is a write request
sl@0
   177
	if (iHostRequestType == ETransferTypeWrite)
sl@0
   178
		{
sl@0
   179
		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request")));
sl@0
   180
		TInt err;		
sl@0
   181
		__THREADREADPLATBUF(aHost, iHostTransferInfo.iDes, iBuffer, err);
sl@0
   182
		if (err != KErrNone)
sl@0
   183
			{
sl@0
   184
			iRequestPending = EFalse;
sl@0
   185
			return err;
sl@0
   186
			}
sl@0
   187
		}
sl@0
   188
	else
sl@0
   189
		{
sl@0
   190
		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request")));
sl@0
   191
		}
sl@0
   192
		
sl@0
   193
	if (iRequestPending)
sl@0
   194
		{
sl@0
   195
		TryToComplete();
sl@0
   196
		}
sl@0
   197
	
sl@0
   198
	return KErrNone;
sl@0
   199
	}
sl@0
   200
sl@0
   201
TInt DTestUsbcEndpoint::TryToComplete()
sl@0
   202
	{
sl@0
   203
	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::TryToComplete")));
sl@0
   204
    TInt err = KErrNone;
sl@0
   205
	TInt len = iHostTransferInfo.iTransferSize - iHostDataTransferred;
sl@0
   206
	
sl@0
   207
	if (SupportsDir(KUsbEpDirBidirect))
sl@0
   208
		{
sl@0
   209
		//Make sure host and client transfer types don't conflict
sl@0
   210
		if (iRequestType == iHostRequestType)
sl@0
   211
			{
sl@0
   212
			iRequestPending = EFalse;
sl@0
   213
			iHostRequestPending = EFalse;
sl@0
   214
			Kern::RequestComplete(iClient, iClientStatus, KErrUsbEpBadDirection);
sl@0
   215
			Kern::RequestComplete(iHost, iHostStatus, KErrUsbEpBadDirection);
sl@0
   216
			return KErrUsbEpBadDirection;
sl@0
   217
			}
sl@0
   218
		}
sl@0
   219
		
sl@0
   220
	if (SupportsDir(KUsbEpDirIn) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeWrite))
sl@0
   221
		{
sl@0
   222
		err = CopyData(iDataTransferred, iHost, iHostTransferInfo.iDes, iHostDataTransferred, len);
sl@0
   223
		}
sl@0
   224
	else if (SupportsDir(KUsbEpDirOut) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeReadData))
sl@0
   225
		{
sl@0
   226
		err = CopyData(iHostDataTransferred, iClient, iClientTransferInfo.iDes, iDataTransferred, len);
sl@0
   227
		}
sl@0
   228
	else
sl@0
   229
		{
sl@0
   230
		err = KErrNotSupported;
sl@0
   231
		}
sl@0
   232
	
sl@0
   233
	if (err != KErrNone)
sl@0
   234
		{
sl@0
   235
		//Problems copying data. Complete requests with error and return.
sl@0
   236
		iRequestPending = EFalse;
sl@0
   237
		iHostRequestPending = EFalse;
sl@0
   238
		Kern::RequestComplete(iClient, iClientStatus, err);
sl@0
   239
		Kern::RequestComplete(iHost, iHostStatus, err);
sl@0
   240
		return err;
sl@0
   241
		}
sl@0
   242
	iDataTransferred += len;
sl@0
   243
	iHostDataTransferred += len;
sl@0
   244
	
sl@0
   245
    iRequestPending = EFalse;
sl@0
   246
    Kern::RequestComplete(iClient, iClientStatus, KErrNone);
sl@0
   247
    iHostRequestPending = EFalse;
sl@0
   248
    Kern::RequestComplete(iHost, iHostStatus, KErrNone);
sl@0
   249
	return KErrNone;
sl@0
   250
	}
sl@0
   251
sl@0
   252
/**
sl@0
   253
Copies data from a source descriptor to a destination descriptor, both in user space.
sl@0
   254
sl@0
   255
@param aSrcClient The thread that owns the source descriptor
sl@0
   256
@param aSrc Pointer to the source descriptor
sl@0
   257
@param aSrcOffset Offset in aSrc from where to start reading data
sl@0
   258
@param aDestClient The thread that owns the destination descriptor
sl@0
   259
@param aDest Pointer to the destination descriptor
sl@0
   260
@param aDestOffset Offset in aDest from where to start writing data
sl@0
   261
@param aLen Amount of bytes to copy
sl@0
   262
@return KErrNone is successful, otherwise a standard Symbian error code
sl@0
   263
*/
sl@0
   264
TInt DTestUsbcEndpoint::CopyData(TInt aSrcOffset, DThread* aDestClient, TDesC8* aDest,
sl@0
   265
								 TInt aDestOffset, TInt aLen)
sl@0
   266
	{	
sl@0
   267
	TInt err;
sl@0
   268
	
sl@0
   269
	// Get the descriptor length in the client's context.
sl@0
   270
	TInt rxLen[2] = {0,0}; 
sl@0
   271
	err=Kern::ThreadRawRead(aDestClient,aDest,&rxLen,sizeof(rxLen));
sl@0
   272
	if (err!=KErrNone)
sl@0
   273
		return err; 
sl@0
   274
	
sl@0
   275
	// copy mo more than max number of chars in receive buffer
sl@0
   276
	aLen = Min(aLen, rxLen[1]);
sl@0
   277
	
sl@0
   278
	while(aLen > 0)
sl@0
   279
		{
sl@0
   280
		TInt len = iBuffer->Length() - aSrcOffset;
sl@0
   281
		//Make sure we only copy aLen bytes, no more
sl@0
   282
		if (len > aLen)
sl@0
   283
			{
sl@0
   284
			len = aLen;
sl@0
   285
			}
sl@0
   286
		TPtrC8 src(iBuffer->Ptr() + aSrcOffset, len);
sl@0
   287
		err = __THREADWRITEOFFSET(aDestClient, aDest, src, aDestOffset);
sl@0
   288
		if (err != KErrNone)
sl@0
   289
			{
sl@0
   290
			return err;
sl@0
   291
			}
sl@0
   292
		aLen -= len;
sl@0
   293
		aSrcOffset += len;
sl@0
   294
		aDestOffset += len;
sl@0
   295
		}
sl@0
   296
	
sl@0
   297
	return KErrNone;
sl@0
   298
	}
sl@0
   299
sl@0
   300
TInt DTestUsbcEndpoint::Halt()
sl@0
   301
	{
sl@0
   302
	iHalted = ETrue;
sl@0
   303
	if (iNotifyHost != NULL)
sl@0
   304
		{
sl@0
   305
		Kern::RequestComplete(iNotifyHost, iHostNotifyStatus, KErrNone);
sl@0
   306
		iNotifyHost = NULL;
sl@0
   307
		}
sl@0
   308
	return KErrNone;
sl@0
   309
	}
sl@0
   310
	
sl@0
   311
TInt DTestUsbcEndpoint::Clear()
sl@0
   312
	{
sl@0
   313
	iHalted = EFalse;
sl@0
   314
	if (iRequestPending)
sl@0
   315
		{
sl@0
   316
		iRequestPending = EFalse;
sl@0
   317
		Kern::RequestComplete(iClient, iClientStatus, KErrNone);
sl@0
   318
		}
sl@0
   319
	if (iHostRequestPending)
sl@0
   320
		{
sl@0
   321
		iHostRequestPending = EFalse;
sl@0
   322
		Kern::RequestComplete(iHost, iHostStatus, KErrNone);
sl@0
   323
		}
sl@0
   324
	if (iClearCallback != NULL)
sl@0
   325
		{
sl@0
   326
		iClearCallback->EndpointStatusNotifyCallback();
sl@0
   327
		}
sl@0
   328
	return KErrNone;
sl@0
   329
	}
sl@0
   330
	
sl@0
   331
void DTestUsbcEndpoint::SetClearCallback(DLddTestUsbcChannel* aCallback)
sl@0
   332
	{
sl@0
   333
	iClearCallback = aCallback;
sl@0
   334
	}
sl@0
   335
	
sl@0
   336
TBool DTestUsbcEndpoint::IsHalted()
sl@0
   337
	{
sl@0
   338
	return iHalted;
sl@0
   339
	}
sl@0
   340
sl@0
   341
TInt DTestUsbcEndpoint::HostStatusNotify(DThread* aHost, TRequestStatus* aStatus)
sl@0
   342
	{
sl@0
   343
	const TRequestStatus s(KRequestPending);
sl@0
   344
	__THREADRAWWRITE(aHost, aStatus, (TUint8*)&s, (TInt)sizeof(TRequestStatus));
sl@0
   345
	iNotifyHost = aHost;
sl@0
   346
	iHostNotifyStatus = aStatus;
sl@0
   347
	return KErrNone;
sl@0
   348
	}
sl@0
   349
	
sl@0
   350
TBool DTestUsbcEndpoint::SupportsDir(TUint aDir)
sl@0
   351
	{
sl@0
   352
	if ((iCaps.iTypesAndDir & aDir) == aDir)
sl@0
   353
		{
sl@0
   354
		return ETrue;
sl@0
   355
		}
sl@0
   356
	return EFalse;
sl@0
   357
	}
sl@0
   358
	
sl@0
   359
TBool DTestUsbcEndpoint::EndpointSuitable(const TUsbcEndpointInfo& aInfo)
sl@0
   360
	{
sl@0
   361
	return (!iReserve &&
sl@0
   362
			(iCaps.iSizes == (TUint)aInfo.iSize) &&
sl@0
   363
			((iCaps.iTypesAndDir & aInfo.iDir) == aInfo.iDir) &&
sl@0
   364
			((iCaps.iTypesAndDir & aInfo.iType) == aInfo.iType));
sl@0
   365
	}
sl@0
   366