kerneltest/e32utils/testusbcldd/src/misc.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32utils/testusbcldd/src/misc.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,366 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32test\testusbcldd\src\misc.cpp
+// 
+//
+
+#include "dtestusblogdev.h"
+
+TUsbcInterface::TUsbcInterface(TUsbcInterfaceSet* aIfcSet, TUint8 aSetting)
+	: iEndpoints(2), iInterfaceSet(aIfcSet), iSettingCode(aSetting)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::TUsbcInterface()")));
+	}
+
+
+TUsbcInterface::~TUsbcInterface()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterface::~TUsbcInterface()")));
+	iEndpoints.ResetAndDestroy();
+	}
+
+
+TUsbcInterfaceSet::TUsbcInterfaceSet(const DBase* aClientId, TUint8 aIfcNum)
+	: iInterfaces(2), iClientId(aClientId), iInterfaceNumber(aIfcNum), iCurrentInterface(0)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::TUsbcInterfaceSet()")));
+	}
+
+
+TUsbcInterfaceSet::~TUsbcInterfaceSet()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceSet::~TUsbcInterfaceSet()")));
+	iInterfaces.ResetAndDestroy();
+	}
+	
+const TUsbcInterface* TUsbcInterfaceSet::CurrentInterface() const
+/** Returns a pointer to the currently selected (active) setting of this interface.
+
+	@return A pointer to the currently selected (active) setting of this interface.
+*/
+	{
+	return iInterfaces[iCurrentInterface];
+	}
+
+
+TUsbcInterface* TUsbcInterfaceSet::CurrentInterface()
+/** Returns a pointer to the currently selected (active) setting of this interface.
+
+	@return A pointer to the currently selected (active) setting of this interface.
+*/
+	{
+	return iInterfaces[iCurrentInterface];
+	}
+
+TUsbcLogicalEndpoint::TUsbcLogicalEndpoint(TUint aEndpointNum, const TUsbcEndpointInfo& aInfo,
+										   TUsbcInterface* aInterface)
+	: iLEndpointNum(aEndpointNum), iInfo(aInfo), iInterface(aInterface)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::TUsbcLogicalEndpoint()")));
+	}
+
+
+TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLogicalEndpoint::~TUsbcLogicalEndpoint: #%d"), iLEndpointNum));
+	}
+
+DTestUsbcEndpoint::DTestUsbcEndpoint()
+	{
+	}
+	
+DTestUsbcEndpoint::~DTestUsbcEndpoint()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Deleting buffer 0x%x"), iBuffer));
+	delete iBuffer;
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Buffer deleted")));
+	}
+	
+TInt DTestUsbcEndpoint::Create(const TUsbcEndpointCaps& aCaps)
+	{
+	iCaps = aCaps;
+	if (iBuffer == NULL)
+		{
+		__NEWPLATBUF(iBuffer, KEndpointBufferSize);
+		if (iBuffer == NULL)
+			return KErrNoMemory;
+		}
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Allocated buffer 0x%x"), iBuffer));
+	return KErrNone;
+	}
+
+void DTestUsbcEndpoint::DoCancel()
+	{
+	if (iRequestPending)
+		{
+		//Cancel client request
+		iRequestPending = EFalse;
+		Kern::RequestComplete(iClient, iClientStatus, KErrCancel);
+		}
+	if (iHostRequestPending)
+		{
+		//Cancel host request
+		iHostRequestPending = EFalse;
+		Kern::RequestComplete(iHost, iHostStatus, KErrCancel);
+		}
+	}
+
+TInt DTestUsbcEndpoint::NewRequest(DThread* aClient, TRequestStatus* aStatus, 
+								   TEndpointTransferInfo& aInfo, TTransferType aType)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewRequest")));
+	//Only supports one request pending per endpoint
+	if (iRequestPending)
+		{
+		return ERequestAlreadyPending;
+		}
+	iClient = aClient;
+	iClientStatus = aStatus;
+	iClientTransferInfo = aInfo;
+	iDataTransferred = 0;
+	iRequestPending = ETrue;
+	iRequestType = aType;
+	
+	//Copy data to local buffer if this is a write request
+	if (iRequestType == ETransferTypeWrite)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request")));
+		TInt err;		
+		__THREADREADPLATBUF(aClient, iClientTransferInfo.iDes, iBuffer, err);
+		if (err != KErrNone)
+			{
+			iRequestPending = EFalse;
+			return err;
+			}
+		}
+	else
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request")));
+		}
+	
+	if (iHostRequestPending)
+		{
+		TryToComplete();
+		}
+	
+	return KErrNone;
+	}
+
+TInt DTestUsbcEndpoint::NewHostRequest(DThread* aHost, TRequestStatus* aStatus,
+									   TEndpointTransferInfo& aInfo, TTransferType aType)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::NewHostRequest")));
+	//Only supports one request pending per endpoint
+	if (iHostRequestPending)
+		{
+		return ERequestAlreadyPending;
+		}
+	iHost = aHost;
+	iHostStatus = aStatus;
+	iHostTransferInfo = aInfo;
+	iHostDataTransferred = 0;
+	iHostRequestPending = ETrue;
+	iHostRequestType = aType;
+	
+	//Copy data to local buffer if this is a write request
+	if (iHostRequestType == ETransferTypeWrite)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Write request")));
+		TInt err;		
+		__THREADREADPLATBUF(aHost, iHostTransferInfo.iDes, iBuffer, err);
+		if (err != KErrNone)
+			{
+			iRequestPending = EFalse;
+			return err;
+			}
+		}
+	else
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("Read request")));
+		}
+		
+	if (iRequestPending)
+		{
+		TryToComplete();
+		}
+	
+	return KErrNone;
+	}
+
+TInt DTestUsbcEndpoint::TryToComplete()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DTestUsbcEndpoint::TryToComplete")));
+    TInt err = KErrNone;
+	TInt len = iHostTransferInfo.iTransferSize - iHostDataTransferred;
+	
+	if (SupportsDir(KUsbEpDirBidirect))
+		{
+		//Make sure host and client transfer types don't conflict
+		if (iRequestType == iHostRequestType)
+			{
+			iRequestPending = EFalse;
+			iHostRequestPending = EFalse;
+			Kern::RequestComplete(iClient, iClientStatus, KErrUsbEpBadDirection);
+			Kern::RequestComplete(iHost, iHostStatus, KErrUsbEpBadDirection);
+			return KErrUsbEpBadDirection;
+			}
+		}
+		
+	if (SupportsDir(KUsbEpDirIn) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeWrite))
+		{
+		err = CopyData(iDataTransferred, iHost, iHostTransferInfo.iDes, iHostDataTransferred, len);
+		}
+	else if (SupportsDir(KUsbEpDirOut) || (SupportsDir(KUsbEpDirBidirect) && iRequestType == ETransferTypeReadData))
+		{
+		err = CopyData(iHostDataTransferred, iClient, iClientTransferInfo.iDes, iDataTransferred, len);
+		}
+	else
+		{
+		err = KErrNotSupported;
+		}
+	
+	if (err != KErrNone)
+		{
+		//Problems copying data. Complete requests with error and return.
+		iRequestPending = EFalse;
+		iHostRequestPending = EFalse;
+		Kern::RequestComplete(iClient, iClientStatus, err);
+		Kern::RequestComplete(iHost, iHostStatus, err);
+		return err;
+		}
+	iDataTransferred += len;
+	iHostDataTransferred += len;
+	
+    iRequestPending = EFalse;
+    Kern::RequestComplete(iClient, iClientStatus, KErrNone);
+    iHostRequestPending = EFalse;
+    Kern::RequestComplete(iHost, iHostStatus, KErrNone);
+	return KErrNone;
+	}
+
+/**
+Copies data from a source descriptor to a destination descriptor, both in user space.
+
+@param aSrcClient The thread that owns the source descriptor
+@param aSrc Pointer to the source descriptor
+@param aSrcOffset Offset in aSrc from where to start reading data
+@param aDestClient The thread that owns the destination descriptor
+@param aDest Pointer to the destination descriptor
+@param aDestOffset Offset in aDest from where to start writing data
+@param aLen Amount of bytes to copy
+@return KErrNone is successful, otherwise a standard Symbian error code
+*/
+TInt DTestUsbcEndpoint::CopyData(TInt aSrcOffset, DThread* aDestClient, TDesC8* aDest,
+								 TInt aDestOffset, TInt aLen)
+	{	
+	TInt err;
+	
+	// Get the descriptor length in the client's context.
+	TInt rxLen[2] = {0,0}; 
+	err=Kern::ThreadRawRead(aDestClient,aDest,&rxLen,sizeof(rxLen));
+	if (err!=KErrNone)
+		return err; 
+	
+	// copy mo more than max number of chars in receive buffer
+	aLen = Min(aLen, rxLen[1]);
+	
+	while(aLen > 0)
+		{
+		TInt len = iBuffer->Length() - aSrcOffset;
+		//Make sure we only copy aLen bytes, no more
+		if (len > aLen)
+			{
+			len = aLen;
+			}
+		TPtrC8 src(iBuffer->Ptr() + aSrcOffset, len);
+		err = __THREADWRITEOFFSET(aDestClient, aDest, src, aDestOffset);
+		if (err != KErrNone)
+			{
+			return err;
+			}
+		aLen -= len;
+		aSrcOffset += len;
+		aDestOffset += len;
+		}
+	
+	return KErrNone;
+	}
+
+TInt DTestUsbcEndpoint::Halt()
+	{
+	iHalted = ETrue;
+	if (iNotifyHost != NULL)
+		{
+		Kern::RequestComplete(iNotifyHost, iHostNotifyStatus, KErrNone);
+		iNotifyHost = NULL;
+		}
+	return KErrNone;
+	}
+	
+TInt DTestUsbcEndpoint::Clear()
+	{
+	iHalted = EFalse;
+	if (iRequestPending)
+		{
+		iRequestPending = EFalse;
+		Kern::RequestComplete(iClient, iClientStatus, KErrNone);
+		}
+	if (iHostRequestPending)
+		{
+		iHostRequestPending = EFalse;
+		Kern::RequestComplete(iHost, iHostStatus, KErrNone);
+		}
+	if (iClearCallback != NULL)
+		{
+		iClearCallback->EndpointStatusNotifyCallback();
+		}
+	return KErrNone;
+	}
+	
+void DTestUsbcEndpoint::SetClearCallback(DLddTestUsbcChannel* aCallback)
+	{
+	iClearCallback = aCallback;
+	}
+	
+TBool DTestUsbcEndpoint::IsHalted()
+	{
+	return iHalted;
+	}
+
+TInt DTestUsbcEndpoint::HostStatusNotify(DThread* aHost, TRequestStatus* aStatus)
+	{
+	const TRequestStatus s(KRequestPending);
+	__THREADRAWWRITE(aHost, aStatus, (TUint8*)&s, (TInt)sizeof(TRequestStatus));
+	iNotifyHost = aHost;
+	iHostNotifyStatus = aStatus;
+	return KErrNone;
+	}
+	
+TBool DTestUsbcEndpoint::SupportsDir(TUint aDir)
+	{
+	if ((iCaps.iTypesAndDir & aDir) == aDir)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+	
+TBool DTestUsbcEndpoint::EndpointSuitable(const TUsbcEndpointInfo& aInfo)
+	{
+	return (!iReserve &&
+			(iCaps.iSizes == (TUint)aInfo.iSize) &&
+			((iCaps.iTypesAndDir & aInfo.iDir) == aInfo.iDir) &&
+			((iCaps.iTypesAndDir & aInfo.iType) == aInfo.iType));
+	}
+