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