kerneltest/e32test/iic/iic_psl/i2c.cpp
changeset 0 a41df078684a
child 6 0173bcd7697c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/iic/iic_psl/i2c.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1078 @@
+// Copyright (c) 2008-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:
+// e32test/iic/iic_psl/I2c.cpp
+//
+
+#include "i2c.h"
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+#include <drivers/iic_trace.h>
+#endif
+
+
+#if defined(MASTER_MODE) && !defined(SLAVE_MODE)
+const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
+#elif defined(MASTER_MODE) && defined(SLAVE_MODE)
+const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
+#else
+const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
+#endif
+#define CHANNEL_TYPE(n) (KChannelTypeArray[n])	
+#define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex)
+
+#ifdef STANDALONE_CHANNEL
+_LIT(KPddNameI2c,"i2c_ctrless.pdd");
+#else
+_LIT(KPddNameI2c,"i2c.pdd");
+#endif
+
+#ifndef STANDALONE_CHANNEL
+LOCAL_C TInt8 AssignChanNum()
+	{
+	static TInt8 iBaseChanNum = KI2cChannelNumBase;
+	I2C_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNum));
+	return iBaseChanNum++; // Arbitrary, for illustration
+	}
+#endif/*STANDALONE_CHANNEL*/
+
+#ifdef SLAVE_MODE
+LOCAL_C TInt16 AssignSlaveChanId()
+	{
+	static TInt16 iBaseSlaveChanId = KI2cSlaveChannelIdBase;
+	I2C_PRINT(("I2C AssignSlaveChanId - on entry, iBaseSlaveChanId = 0x%x\n",iBaseSlaveChanId));
+	return iBaseSlaveChanId++; // Arbitrary, for illustration
+	}
+#endif/*SLAVE_MODE*/
+
+NONSHARABLE_CLASS(DSimulatedI2cDevice) : public DPhysicalDevice
+	{
+// Class to faciliate loading of the IIC classes
+public:
+	class TCaps
+		{
+	public:
+		TVersion iVersion;
+		};
+public:
+	DSimulatedI2cDevice();
+	virtual TInt Install();
+	virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual void GetCaps(TDes8& aDes) const;
+	inline static TVersion VersionRequired();
+	};
+
+TVersion DSimulatedI2cDevice::VersionRequired()
+	{
+	I2C_PRINT(("DSimulatedI2cDevice::VersionRequired\n"));
+	return TVersion(KIicClientMajorVersionNumber,KIicClientMinorVersionNumber,KIicClientBuildVersionNumber);
+	}
+
+/** Factory class constructor */
+DSimulatedI2cDevice::DSimulatedI2cDevice()
+	{
+	I2C_PRINT(("DSimulatedI2cDevice::DSimulatedI2cDevice\n"));
+    iVersion = DSimulatedI2cDevice::VersionRequired();
+	}
+
+TInt DSimulatedI2cDevice::Install()
+    {
+	I2C_PRINT(("DSimulatedI2cDevice::Install\n"));
+    return(SetName(&KPddNameI2c));
+    }
+
+/**  Called by the kernel's device driver framework to create a Physical Channel. */
+TInt DSimulatedI2cDevice::Create(DBase*& /*aChannel*/, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
+    {
+	I2C_PRINT(("DSimulatedI2cDevice::Create\n"));
+    return KErrNone;
+    }
+
+/**  Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
+TInt DSimulatedI2cDevice::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
+    {
+	I2C_PRINT(("DSimulatedI2cDevice::Validate\n"));
+   	if (!Kern::QueryVersionSupported(DSimulatedI2cDevice::VersionRequired(),aVer))
+		return(KErrNotSupported);
+    return KErrNone;
+    }
+
+/** Return the driver capabilities */
+void DSimulatedI2cDevice::GetCaps(TDes8& aDes) const
+    {
+	I2C_PRINT(("DSimulatedI2cDevice::GetCaps\n"));
+	// Create a capabilities object
+	TCaps caps;
+	caps.iVersion = iVersion;
+	// Zero the buffer
+	TInt maxLen = aDes.MaxLength();
+	aDes.FillZ(maxLen);
+	// Copy capabilities
+	TInt size=sizeof(caps);
+	if(size>maxLen)
+	   size=maxLen;
+	aDes.Copy((TUint8*)&caps,size);
+    }
+
+
+DSimulatedI2cDevice* gDummyDevice;
+
+
+// supported channels for this implementation
+static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS];
+
+
+//DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY)	
+DECLARE_STANDARD_PDD()		// I2c test driver to be explicitly loaded as an LDD, not kernel extension
+	{	
+	if(gDummyDevice == NULL)
+		gDummyDevice = new DSimulatedI2cDevice;
+	if(gDummyDevice == NULL)
+		return NULL;
+	I2C_PRINT(("\n\nI2C PDD, channel creation loop follows ...\n"));
+
+#ifndef STANDALONE_CHANNEL
+	DIicBusChannel* chan=NULL;
+	for(TInt i=0; i<NUM_CHANNELS; i++)
+		{
+	I2C_PRINT(("\n"));
+#if defined(MASTER_MODE)
+		if(CHANNEL_TYPE(i) == (DIicBusChannel::EMaster))
+			{
+			chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
+			if(!chan)
+				return NULL;
+			I2C_PRINT(("I2C chan created at 0x%x\n",chan));
+			if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
+			    {
+			    delete chan;
+				return NULL;
+                }
+			}
+#endif
+#if defined(MASTER_MODE) && defined(SLAVE_MODE)
+		if(CHANNEL_TYPE(i) == DIicBusChannel::EMasterSlave)
+			{
+			DIicBusChannel* chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
+			if(!chanM)
+				return NULL;
+			DIicBusChannel* chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
+			if(!chanS)
+			    {
+			    delete chanM;
+				return NULL;
+			    }
+			// For MasterSlave channel, the channel number for both the Master and Slave channels must be the same
+			TInt8 msChanNum = ((DSimulatedIicBusChannelMasterI2c*)chanM)->GetChanNum();
+			((DSimulatedIicBusChannelSlaveI2c*)chanS)->SetChanNum(msChanNum);
+
+			chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
+			if(!chan)
+			    {
+			    delete chanM;
+			    delete chanS;
+				return NULL;
+			    }
+			I2C_PRINT(("I2C chan created at 0x%x\n",chan));
+			if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
+			    {
+			    delete chanM;
+			    delete chanS;
+			    delete chan;
+				return NULL;
+			    }
+			}
+#endif
+#if defined(SLAVE_MODE)
+		if(CHANNEL_TYPE(i) == (DIicBusChannel::ESlave))
+			{
+			chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
+			if(!chan)
+				return NULL;
+			I2C_PRINT(("I2C chan created at 0x%x\n",chan));
+			if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
+			    {
+			    delete chan;
+			    return NULL;
+			    }
+			}
+#endif
+#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
+#error I2C mode not defined as Master, Slave nor Master-Slave
+#endif
+		if(chan == NULL)
+			{
+			I2C_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
+			return NULL;
+			}
+		ChannelPtrArray[i]=chan;
+		}
+	I2C_PRINT(("\nI2C PDD, channel creation loop done- about to invoke RegisterChannels\n\n"));
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_REGISTERCHANS_START_PSL_TRACE;
+#endif
+
+	TInt r=DIicBusController::RegisterChannels(ChannelPtrArray,NUM_CHANNELS);
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_REGISTERCHANS_END_PSL_TRACE;
+#endif
+	I2C_PRINT(("\nI2C - returned from RegisterChannels with r=%d\n",r));
+	if(r!=KErrNone)
+		{
+		delete chan;
+		return NULL;
+		}
+#endif
+	return gDummyDevice;
+	}
+
+
+#ifdef MASTER_MODE
+#ifdef STANDALONE_CHANNEL
+EXPORT_C
+#endif
+DSimulatedIicBusChannelMasterI2c::DSimulatedIicBusChannelMasterI2c(const TBusType aBusType, const TChannelDuplex aChanDuplex)
+	: DIicBusChannelMaster(aBusType,aChanDuplex)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DSimulatedIicBusChannelMasterI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex));
+#ifndef STANDALONE_CHANNEL
+	iChannelNumber = AssignChanNum();
+#endif
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DSimulatedIicBusChannelMasterI2c, iChannelNumber=%d\n",iChannelNumber));
+	}
+
+TInt DSimulatedIicBusChannelMasterI2c::DoCreate()
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoCreate\n"));
+	TInt r=Init();	// PIL Base class initialisation
+	r=Kern::DynamicDfcQCreate(iDynamicDfcQ,KI2cThreadPriority,KI2cThreadName);
+	if(r == KErrNone)
+		SetDfcQ((TDfcQue*)iDynamicDfcQ);
+	DSimulatedIicBusChannelMasterI2c::SetRequestDelayed(this,EFalse);
+	return r;
+	}
+
+TInt DSimulatedIicBusChannelMasterI2c::CheckHdr(TDes8* aHdr)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::CheckHdr\n"));
+
+	TConfigI2cBufV01* i2cBuf = (TConfigI2cBufV01*)aHdr;
+	TConfigI2cV01* i2cPtr = &((*i2cBuf)());
+
+	// Check that the values for address type, clock speed, user operation and endianness are recognised
+	if((i2cPtr->iAddrType < 0) || (i2cPtr->iAddrType > EI2cAddr10Bit))
+		{
+		I2C_PRINT(("ERROR: DSimulatedIicBusChannelMasterI2c::CheckHdr unrecognised address type identifier %d\n",i2cPtr->iAddrType));
+		return KErrArgument;
+		}
+	if(i2cPtr->iClkSpeedHz < 0)
+		{
+		I2C_PRINT(("ERROR: DSimulatedIicBusChannelMasterI2c::CheckHdr negative clock speed specified %d\n",i2cPtr->iClkSpeedHz));
+		return KErrArgument;
+		}
+	if((i2cPtr->iEndianness < 0) || (i2cPtr->iEndianness > ELittleEndian))
+		{
+		I2C_PRINT(("ERROR: DSimulatedIicBusChannelMasterI2c::CheckHdr unrecognised endianness identifier %d\n",i2cPtr->iEndianness));
+		return KErrArgument;
+		}
+	// Values for the timeout period are arbitrary - can only check it is not a negative value
+	if(i2cPtr->iTimeoutPeriod < 0)
+		{
+		I2C_PRINT(("ERROR: DSimulatedIicBusChannelMasterI2c::CheckHdr negative timeout period %d\n",i2cPtr->iTimeoutPeriod));
+		return KErrArgument;
+		}
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::CheckHdr address type = %d\n",i2cPtr->iAddrType));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::CheckHdr clock speed ID = %d\n",i2cPtr->iClkSpeedHz));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::CheckHdr iEndianness ID = %d\n",i2cPtr->iEndianness));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::CheckHdr iTimeoutPeriod = %d\n",i2cPtr->iTimeoutPeriod));
+	return KErrNone;
+	}
+
+	// Gateway function for PSL implementation, invoked for DFC processing
+TInt DSimulatedIicBusChannelMasterI2c::DoRequest(TIicBusTransaction* aTransaction)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest invoked with aTransaction=0x%x\n",aTransaction));
+	TInt r = KErrNone;
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_MPROCESSTRANS_START_PSL_TRACE;
+#endif
+
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans aTransaction->iHeader=0x%x\n",GetTransactionHeader(aTransaction)));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans aTransaction->iHalfDuplexTrans=0x%x\n",GetTransHalfDuplexTferPtr(aTransaction)));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans aTransaction->iFullDuplexTrans=0x%x\n",GetTransFullDuplexTferPtr(aTransaction)));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans aTransaction->iCallback=0x%x\n",GetTransCallback(aTransaction)));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans aTransaction->iFlags=0x%x\n",GetTransFlags(aTransaction)));
+
+	I2C_PRINT(("\nDSimulatedIicBusChannelMasterI2c::DoRequest, iHeader info \n"));
+	TDes8* bufPtr = GetTransactionHeader(aTransaction);
+	if(bufPtr == NULL)
+		{
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest ERROR - NULL header\n"));
+		return KErrCorrupt;
+		}
+	TConfigI2cV01 *buf = (TConfigI2cV01 *)(bufPtr->Ptr());
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest, header address type=0x%x\n",buf->iAddrType));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest, header clock speed=0x%x\n",buf->iClkSpeedHz));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest, header endianness=0x%x\n",buf->iEndianness));
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::DoRequest, header timeout period=0x%x\n",buf->iTimeoutPeriod));
+	(void)buf;	// Silence compiler when I2C_PRINT not used
+
+	TInt aTime=1000000/NKern::TickPeriod();
+	r = StartSlaveTimeOutTimer(aTime);
+	I2C_PRINT(("\nDSimulatedIicBusChannelMasterI2c::ProcessTrans, iHalfDuplexTrans info \n"));
+	TIicBusTransfer* halfDuplexPtr=GetTransHalfDuplexTferPtr(aTransaction);
+	while(halfDuplexPtr != NULL)
+		{
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans transfer type=0x%x\n",GetTferType(halfDuplexPtr)));
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans granularity=0x%x\n",GetTferBufGranularity(halfDuplexPtr)));
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans transfer buffer=0x%x\n",GetTferBuffer(halfDuplexPtr)));
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans next transfer =0x%x\n",GetTferNextTfer(halfDuplexPtr)));
+		halfDuplexPtr=GetTferNextTfer(halfDuplexPtr);
+		}
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans - End of iHalfDuplexTrans info"));
+
+	while(IsRequestDelayed(this))
+		{
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans - starting Sleep...\n"));
+		NKern::Sleep(1000);	// 1000 is arbitrary
+		I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans - completed Sleep, check if still delayed\n"));
+		}; 
+
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::ProcessTrans - exiting\n"));
+
+	return r;
+	}
+
+
+TBool DSimulatedIicBusChannelMasterI2c::IsRequestDelayed(DSimulatedIicBusChannelMasterI2c* aChan)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::IsRequestDelayed invoked for aChan=0x%x\n",aChan));
+	return aChan->iReqDelayed;
+	}
+
+void DSimulatedIicBusChannelMasterI2c::SetRequestDelayed(DSimulatedIicBusChannelMasterI2c* aChan,TBool aDelay) 
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::SetRequestDelayed invoked for aChan=0x%x, with aDelay=0x%d\n",aChan,aDelay));
+	aChan->iReqDelayed=aDelay;
+	}
+
+TInt DSimulatedIicBusChannelMasterI2c::HandleSlaveTimeout()
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::HandleSlaveTimeout invoked for this=0x%x\n",this));
+	return KErrTimedOut;
+	}
+
+TInt DSimulatedIicBusChannelMasterI2c::StaticExtension(TUint aFunction, TAny* aParam1, TAny* aParam2)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::StaticExtension\n"));
+	TInt r = KErrNone;
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_MSTATEXT_START_PSL_TRACE;
+#endif
+	(void)aParam1;
+	(void)aParam2;
+	
+	// Test values of aFunction were shifted left one place by the (test) client driver
+	// Return to its original value.
+	if(aFunction>KTestControlIoPilOffset)
+		aFunction >>= 1;
+	switch(aFunction)
+		{
+		case(RBusDevIicClient::ECtlIoDumpChan):
+			{
+#ifdef _DEBUG
+			DumpChannel();
+#endif
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoBlockReqCompletion):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::Blocking request completion\n"));
+			SetRequestDelayed(this, ETrue);
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelMasterI2c::Unlocking request completion\n"));
+			SetRequestDelayed(this, EFalse);
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoDeRegChan):
+			{
+#ifndef STANDALONE_CHANNEL
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_DEREGISTERCHAN_START_PSL_TRACE;
+#endif
+			I2C_PRINT(("DSimulatedIicBusChannelMasterI2c: deregister channel\n"));
+			r=DIicBusController::DeRegisterChannel(this);
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_DEREGISTERCHAN_END_PSL_TRACE;
+#endif/*IIC_INSTRUMENTATION_MACRO*/
+	
+#else/*STANDALONE_CHANNEL*/
+			r = KErrNotSupported;
+#endif/*STANDALONE_CHANNEL*/
+			break;
+			}
+		default:
+			{
+			Kern::Printf("aFunction %d is not recognised \n",aFunction);
+			r=KErrNotSupported;
+			}
+		}
+		
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_MSTATEXT_END_PSL_TRACE;
+#endif		
+	return r;
+	}
+
+//#ifdef MASTER_MODE
+#endif
+
+#ifdef SLAVE_MODE
+
+void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr)
+	{
+	// To support simulating an asynchronous capture operation
+	// NOTE: this will be invoked in the context of DfcThread1
+	I2C_PRINT(("SlaveAsyncSimCallback\n"));
+	DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr;
+	TInt r=KErrNone;// Just simulate successful capture
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SCAPTCHANASYNC_END_PSL_TRACE;
+#endif
+	channel->ChanCaptureCb(r);
+	}
+
+#ifdef STANDALONE_CHANNEL
+EXPORT_C
+#endif
+DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex)
+	: DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class
+	iBlockedTrigger(0),iBlockNotification(EFalse),
+	iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex));
+#ifndef STANDALONE_CHANNEL
+	iChannelNumber = AssignChanNum();
+#endif
+	iChannelId = AssignSlaveChanId();
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, iChannelNumber=%d, iChannelId=0x%x\n",iChannelNumber,iChannelId));
+	}
+
+DSimulatedIicBusChannelSlaveI2c::~DSimulatedIicBusChannelSlaveI2c()
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::~DSimulatedIicBusChannelSlaveI2c\n"));
+	}
+
+TInt DSimulatedIicBusChannelSlaveI2c::DoCreate()
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DoCreate\n"));
+	TInt r=Init();	// PIL Base class initialisation
+	return r;
+	}
+
+
+TInt DSimulatedIicBusChannelSlaveI2c::CaptureChannelPsl(TBool aAsynch)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::CaptureChannelPsl\n"));
+	TInt r = KErrNone;
+	if(aAsynch)
+		{
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SCAPTCHANASYNC_START_PSL_TRACE;
+#endif
+		// To simulate an asynchronous capture operation, just set a timer to expire
+		iSlaveTimer.OneShot(1000, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1
+		}
+	else
+		{
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SCAPTCHANSYNC_START_PSL_TRACE;
+#endif
+		// PSL processing would happen here ...
+		// Expected to include implementation of the header configuration information 
+
+		I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::CaptureChannelPsl (synchronous) ... no real processing to do \n"));
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SCAPTCHANSYNC_END_PSL_TRACE;
+#endif
+		}
+
+	return r;
+	}
+
+TInt DSimulatedIicBusChannelSlaveI2c::ReleaseChannelPsl()
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::ReleaseChannelPsl\n"));
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SRELCHAN_START_PSL_TRACE;
+#endif
+	TInt r = KErrNone;
+
+	// PSL-specific processing would happen here ...
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::ReleaseChannelPsl ... no real processing to do \n"));
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SRELCHAN_END_PSL_TRACE;
+#endif
+
+	return r;
+	}
+
+
+TInt DSimulatedIicBusChannelSlaveI2c::PrepareTrigger(TInt aTrigger)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::PrepareTrigger\n"));
+#ifdef IIC_INSTRUMENTATION_MACRO
+//	IIC_SNOTIFTRIG_START_PSL;
+#endif
+	TInt r=KErrNotSupported;
+	if(aTrigger&EReceive)
+		{
+		I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::PrepareTrigger - prepare hardware for Rx\n"));
+		r=KErrNone;
+		}
+	if(aTrigger&ETransmit)
+		{
+		I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::PrepareTrigger - prepare hardware for Tx\n"));
+		r=KErrNone;
+		}
+	// Check for any additional triggers and make the necessary preparation
+	// ... do nothing in simulated PSL
+	r=KErrNone;
+
+#ifdef IIC_INSTRUMENTATION_MACRO
+//	IIC_SNOTIFTRIG_END_PSL;
+#endif
+	return r;
+	}
+
+TInt DSimulatedIicBusChannelSlaveI2c::CheckHdr(TDes8* /*aHdr*/)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::CheckHdr\n"));
+	return KErrNone;
+	}
+
+TInt DSimulatedIicBusChannelSlaveI2c::DoRequest(TInt aOperation)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DoRequest\n"));
+	TInt r = KErrNone;
+
+	switch(aOperation)
+		{
+		case(ESyncConfigPwrUp):
+			{
+			r=CaptureChannelPsl(EFalse);
+			break;
+			};
+		case(EAsyncConfigPwrUp):
+			{
+			r=CaptureChannelPsl(ETrue);
+			break;
+			};
+		case(EPowerDown):
+			{
+			r=ReleaseChannelPsl();
+			break;
+			};
+		case(EAbort):
+			{
+			break;
+			};
+		default:
+			{
+			// The remaining operations are to instigate an Rx, Tx or just prepare for
+			// overrun/underrun/bus error notifications.
+			// Handle all these, and any unsupported operation in the following function
+			r=PrepareTrigger(aOperation);
+			break;
+			};
+		}
+	return r;
+	}
+
+void DSimulatedIicBusChannelSlaveI2c::ProcessData(TInt aTrigger, TIicBusSlaveCallback*  aCb)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::ProcessData\n"));
+	// fills in iReturn, iRxWords and/or iTxWords
+	//
+	if(aTrigger & ERxAllBytes)
+		{
+		aCb->SetRxWords(iNumWordsWereRx);
+		if(iRxTxUnderOverRun & ERxUnderrun)
+			{
+			aTrigger|=ERxUnderrun;
+			iRxTxUnderOverRun&= ~ERxUnderrun;
+			}
+		if(iRxTxUnderOverRun & ERxOverrun)
+			{
+			aTrigger|=ERxOverrun;
+			iRxTxUnderOverRun&= ~ERxOverrun;
+			}
+		}
+	if(aTrigger & ETxAllBytes)
+		{
+		aCb->SetTxWords(iNumWordsWereTx);
+		if(iRxTxUnderOverRun & ETxUnderrun)
+			{
+			aTrigger|=ETxUnderrun;
+			iRxTxUnderOverRun&= ~ETxUnderrun;
+			}
+		if(iRxTxUnderOverRun & ETxOverrun)
+			{
+			aTrigger|=ETxOverrun;
+			iRxTxUnderOverRun&= ~ETxOverrun;
+			}
+		}
+
+	aCb->SetTrigger(aTrigger);
+	}
+
+TInt DSimulatedIicBusChannelSlaveI2c::StaticExtension(TUint aFunction, TAny* aParam1, TAny* aParam2)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::StaticExtension\n"));
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SSTATEXT_START_PSL_TRACE;
+#endif
+	// Test values of aFunction were shifted left one place by the (test) client driver
+	// and for Slave values the two msb were cleared
+	// Return to its original value.
+	if(aFunction>KTestControlIoPilOffset)
+		{
+		aFunction |= 0xC0000000;
+		aFunction >>= 1;
+		}
+	TInt r = KErrNone;
+	switch(aFunction)
+		{
+		case(RBusDevIicClient::ECtlIoDumpChan):
+			{
+#ifdef _DEBUG
+			DumpChannel();
+#endif
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoDeRegChan):
+			{
+#ifndef STANDALONE_CHANNEL
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: deregister channel\n"));
+			// DIicBusController::DeRegisterChannel just removes the channel from the array of channels available 
+			r=DIicBusController::DeRegisterChannel(this);
+#else
+			r = KErrNotSupported;
+#endif
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoRxWords):
+			{
+			// Simulate receipt of a number of bytes
+			// aParam1 represents the ChannelId
+			// aParam2 specifies the number of bytes
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoRxWords, channelId=0x%x, numBytes=0x%x\n",aParam1,aParam2));
+
+			// Load the buffer with simulated data
+			if(iRxBuf == NULL)
+				{
+				I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoRxWords, ERROR, iRxBuf == NULL\n"));
+				r=KErrGeneral;
+				break;
+				}
+			// Check for overrun-underrun conditions
+			TInt trigger=ERxAllBytes;
+			iNumWordsWereRx=(TInt8)((TInt)aParam2);
+			iDeltaWordsToRx = (TInt8)(iNumWordsWereRx - iNumRxWords);
+			if(iDeltaWordsToRx>0)
+				{
+				iNumWordsWereRx=iNumRxWords;
+				iRxTxUnderOverRun |= ERxOverrun;
+				}
+			if(iDeltaWordsToRx<0)
+				iRxTxUnderOverRun |= ERxUnderrun;
+
+			TInt8* ptr=(TInt8*)(iRxBuf+iRxOffset);
+			TInt8 startVal=0x10;
+			for(TInt8 numWords=0; numWords<iNumWordsWereRx; numWords++,startVal++)
+				{
+				for(TInt wordByte=0; wordByte<iRxGranularity; wordByte++,ptr++)
+					{
+					*ptr=startVal;
+					}
+				}
+			if(iBlockNotification == EFalse)
+				{
+				//
+				// Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback
+				NotifyClient(trigger);
+				}
+			else
+				{
+				// Save the trigger value to notify when prompted.
+				iBlockedTrigger=trigger;
+				}
+			break;
+
+			}
+
+		case(RBusDevIicClient::ECtrlIoUnblockNotification):
+			{
+			iBlockNotification=EFalse;
+			NotifyClient(iBlockedTrigger);
+			iBlockedTrigger=0;
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoBlockNotification):
+			{
+			iBlockNotification=ETrue;
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoTxWords):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoTxWords, aParam1=0x%x, aParam2=0x%x\n",aParam1,aParam2));
+			// Simulate transmission of a number of bytes
+			// aParam1 represents the ChannelId
+			// aParam2 specifies the number of bytes
+			// Load the buffer with simulated data
+			if(iTxBuf == NULL)
+				{
+				I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoTxWords, ERROR, iTxBuf==NULL\n"));
+				r=KErrGeneral;
+				break;
+				}
+			// Check for overrun-underrun conditions
+			TInt trigger=ETxAllBytes;
+			iNumWordsWereTx=(TInt8)((TInt)aParam2);
+			iDeltaWordsToTx = (TInt8)(iNumWordsWereTx - iNumTxWords);
+			if(iDeltaWordsToTx>0)
+				{
+				iNumWordsWereTx=iNumTxWords;
+				iRxTxUnderOverRun |= ETxUnderrun;
+				}
+			if(iDeltaWordsToTx<0)
+				iRxTxUnderOverRun |= ETxOverrun;
+
+			// Initialise the check buffer
+			if(iTxCheckBuf!=NULL)
+				delete iTxCheckBuf;
+			// iTxCheckBuf is a member of class DSimulatedIicBusChannelSlaveI2c, which 
+			// is created here, and deleted not in ~DSimulatedIicBusChannelSlaveI2c()
+			// but from client side. This is because in t_iic, 
+			// we put a memory leak checking macro __KHEAP_MARKEND before
+			// the pdd gets unloaded which will call ~DSimulatedIicBusChannelSlaveI2c().  
+			// If we delete iTxCheckBuf in ~DSimulatedIicBusChannelSlaveI2c(),
+			// we will get a memory leak panic in __KHEAP_MARKEND.
+			// To support the test code, we moved iTxCheckBuf deletion to the client side. 
+			iTxCheckBuf = new TInt8[iNumTxWords*iTxGranularity];
+			memset(iTxCheckBuf,0,(iNumTxWords*iTxGranularity));
+
+			TInt8* srcPtr=(TInt8*)(iTxBuf+iTxOffset);
+			TInt8* dstPtr=iTxCheckBuf;
+			for(TInt8 numWords=0; numWords<iNumWordsWereTx; numWords++)
+				{
+				for(TInt wordByte=0; wordByte<iTxGranularity; wordByte++)
+					*dstPtr++=*srcPtr++;
+				}
+			if(iBlockNotification == EFalse)
+				{
+				//
+				// Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback
+				NotifyClient(trigger);
+				}
+			else
+				{
+				// Save the trigger value to notify when prompted.
+				iBlockedTrigger=trigger;
+				}
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoRxTxWords):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoRxTxWords, aParam1=0x%x, aParam2=0x%x\n",aParam1,aParam2));
+			// Simulate transmission of a number of bytes
+			// aParam1 represents the ChannelId
+			// aParam2 represents a pointer to the two numbers of bytes
+			// Check the buffers are available
+			if(iTxBuf == NULL)
+				{
+				I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoRxTxWords, ERROR, iTxBuf==NULL\n"));
+				r=KErrGeneral;
+				break;
+				}
+			if(iRxBuf == NULL)
+				{
+				I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoRxTxWords, ERROR, iRxBuf==NULL\n"));
+				r=KErrGeneral;
+				break;
+				}
+			// Check for overrun-underrun conditions
+			TInt trigger=ETxAllBytes|ERxAllBytes;
+			iNumWordsWereRx=(TInt8)(*(TInt*)aParam2);
+			TInt* tempPtr=((TInt*)(aParam2));
+			iNumWordsWereTx=(TInt8)(*(++tempPtr));
+
+			iDeltaWordsToTx = (TInt8)(iNumWordsWereTx - iNumTxWords);
+			if(iDeltaWordsToTx>0)
+				{
+				iNumWordsWereTx=iNumTxWords;
+				iRxTxUnderOverRun |= ETxUnderrun;
+				}
+			if(iDeltaWordsToTx<0)
+				iRxTxUnderOverRun |= ETxOverrun;
+
+
+			iDeltaWordsToRx = (TInt8)(iNumWordsWereRx - iNumRxWords);
+			if(iDeltaWordsToRx>0)
+				{
+				iNumWordsWereRx=iNumRxWords;
+				iRxTxUnderOverRun |= ERxOverrun;
+				}
+			if(iDeltaWordsToRx<0)
+				iRxTxUnderOverRun |= ERxUnderrun;
+
+
+			// Initialise the buffers
+			if(iTxCheckBuf!=NULL)
+				delete iTxCheckBuf;
+			iTxCheckBuf = new TInt8[iNumTxWords*iTxGranularity];
+			memset(iTxCheckBuf,0,(iNumTxWords*iTxGranularity));
+
+			TInt8* srcPtr=(TInt8*)(iTxBuf+iTxOffset);
+			TInt8* dstPtr=iTxCheckBuf;
+			TInt8 numWords=0;
+			for(numWords=0; numWords<iNumWordsWereTx; numWords++)
+				{
+				for(TInt wordByte=0; wordByte<iTxGranularity; wordByte++)
+					*dstPtr++=*srcPtr++;
+				}
+
+			TInt8* ptr=(TInt8*)(iRxBuf+iRxOffset);
+			TInt8 startVal=0x10;
+			for(numWords=0; numWords<iNumWordsWereRx; numWords++,startVal++)
+				{
+				for(TInt wordByte=0; wordByte<iRxGranularity; wordByte++,ptr++)
+					{
+					*ptr=startVal;
+					}
+				}		
+			
+			if(iBlockNotification == EFalse)
+				{
+				//
+				// Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback
+				NotifyClient(trigger);
+				}
+			else
+				{
+				// Save the trigger value to notify when prompted.
+				iBlockedTrigger=trigger;
+				}
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoTxChkBuf):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtrlIoTxChkBuf, aParam1=0x%x, aParam2=0x%x\n",aParam1,aParam2));
+			// Return the address of iTxCheckBuf to the address pointed to by a1
+			// Both the simulated bus channel and the slave client are resident in the client process
+			// so the client can use the pointer value for direct access
+			TInt8** ptr = (TInt8**)aParam1;
+			*ptr=iTxCheckBuf;
+			break;
+			}
+
+		case(RBusDevIicClient::ECtlIoBusError):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c: ECtlIoBusError\n"));
+			NotifyClient(EGeneralBusError);
+			break;
+			}
+
+		case(RBusDevIicClient::ECtrlIoUpdTimeout):
+			{
+			// For this test, do the following for the Master and Client timeout values:
+			// (1) Read the current timeout value and check that it is set to the default
+			// (2) Check setting to a neagtive value fails
+			// (3) Set it to a new, different value
+			// (4) Read it back to check success
+			// (5) Return to the original value, and readback to confirm
+			I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c ECtrlIoUpdTimeout \n"));
+
+			TInt timeout = 0;
+			TInt r=KErrNone;
+			// Master timeout
+			timeout=GetMasterWaitTime();
+			if(timeout!=KSlaveDefMWaitTime)
+				{
+				I2C_PRINT(("ERROR: Initial Master Wait time != KSlaveDefMWaitTime (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			r=SetMasterWaitTime(-1);
+			if(r!=KErrArgument)
+				{
+				I2C_PRINT(("ERROR: Attempt to set negative Master wait time not rejected\n"));
+				return KErrGeneral;
+				}
+			r=SetMasterWaitTime(KSlaveDefCWaitTime);
+			if(r!=KErrNone)
+				{
+				I2C_PRINT(("ERROR: Attempt to set new valid Master wait time (%d) rejected\n",KSlaveDefCWaitTime));
+				return KErrGeneral;
+				}
+			timeout=GetMasterWaitTime();
+			if(timeout!=KSlaveDefCWaitTime)
+				{
+				I2C_PRINT(("ERROR: Master Wait time read back has unexpected value (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			r=SetMasterWaitTime(KSlaveDefMWaitTime);
+			if(r!=KErrNone)
+				{
+				I2C_PRINT(("ERROR: Attempt to set reset Master wait time (%d) rejected\n",KSlaveDefMWaitTime));
+				return KErrGeneral;
+				}
+			timeout=GetMasterWaitTime();
+			if(timeout!=KSlaveDefMWaitTime)
+				{
+				I2C_PRINT(("ERROR: Master Wait time read back of reset time has unexpected value (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			// Client timeout
+			timeout=GetClientWaitTime();
+			if(timeout!=KSlaveDefCWaitTime)
+				{
+				I2C_PRINT(("ERROR: Initial Client Wait time != KSlaveDefCWaitTime (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			r=SetClientWaitTime(-1);
+			if(r!=KErrArgument)
+				{
+				I2C_PRINT(("ERROR: Attempt to set negative Client wait time not rejected\n"));
+				return KErrGeneral;
+				}
+			r=SetClientWaitTime(KSlaveDefMWaitTime+1);
+			if(r!=KErrNone)
+				{
+				I2C_PRINT(("ERROR: Attempt to set new valid Client wait time (%d) rejected\n",KSlaveDefMWaitTime));
+				return KErrGeneral;
+				}
+			timeout=GetClientWaitTime();
+			if(timeout!=KSlaveDefMWaitTime+1)
+				{
+				I2C_PRINT(("ERROR: Client Wait time read back has unexpected value (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			r=SetClientWaitTime(KSlaveDefCWaitTime);
+			if(r!=KErrNone)
+				{
+				I2C_PRINT(("ERROR: Attempt to set reset Client wait time (%d) rejected\n",KSlaveDefCWaitTime));
+				return KErrGeneral;
+				}
+			timeout=GetClientWaitTime();
+			if(timeout!=KSlaveDefCWaitTime)
+				{
+				I2C_PRINT(("ERROR: Client Wait time read back of reset time has unexpected value (=%d) \n",timeout));
+				return KErrGeneral;
+				}
+			break;
+			}
+
+		default:
+			{
+			Kern::Printf("aFunction %d is not recognised \n",aFunction);
+			r=KErrNotSupported;
+			}
+		}
+#ifdef IIC_INSTRUMENTATION_MACRO
+	IIC_SSTATEXT_END_PSL_TRACE;
+#endif
+	return r;
+	}
+
+
+
+//#ifdef MASTER_MODE
+#endif
+
+#if defined(MASTER_MODE) && defined(SLAVE_MODE)
+#ifdef STANDALONE_CHANNEL
+EXPORT_C
+#endif
+DSimulatedIicBusChannelMasterSlaveI2c::DSimulatedIicBusChannelMasterSlaveI2c(TBusType /*aBusType*/, TChannelDuplex aChanDuplex, DSimulatedIicBusChannelMasterI2c* aMasterChan, DSimulatedIicBusChannelSlaveI2c* aSlaveChan)
+	: DIicBusChannelMasterSlave(EI2c, aChanDuplex, aMasterChan, aSlaveChan)
+	{}
+
+TInt DSimulatedIicBusChannelMasterSlaveI2c::StaticExtension(TUint aFunction, TAny* /*aParam1*/, TAny* /*aParam2*/)
+	{
+	I2C_PRINT(("DSimulatedIicBusChannelMasterSlaveI2c::StaticExtension, aFunction=0x%x\n",aFunction));
+	TInt r = KErrNone;
+
+	// Test values of aFunction were shifted left one place by the (test) client driver
+	// Return to its original value.
+	if(aFunction>KTestControlIoPilOffset)
+		aFunction >>= 1;
+	switch(aFunction)
+		{
+		case(RBusDevIicClient::ECtlIoDumpChan):
+			{
+#ifdef _DEBUG
+			DumpChannel();
+#endif
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoDeRegChan):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelMasterSlaveI2c: deregister channel\n"));
+#ifndef STANDALONE_CHANNEL
+			r=DIicBusController::DeRegisterChannel(this);
+#else
+			return KErrNotSupported;
+#endif
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoBlockReqCompletion):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelMasterSlaveI2c::Blocking request completion\n"));
+			((DSimulatedIicBusChannelMasterI2c*)iMasterChannel)->SetRequestDelayed(((DSimulatedIicBusChannelMasterI2c*)iMasterChannel), ETrue);
+			break;
+			}
+		case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
+			{
+			I2C_PRINT(("DSimulatedIicBusChannelMasterSlaveI2c::Unlocking request completion\n"));
+			((DSimulatedIicBusChannelMasterI2c*)iMasterChannel)->SetRequestDelayed(((DSimulatedIicBusChannelMasterI2c*)iMasterChannel), EFalse);
+			break;
+			}
+		default:
+			{
+			Kern::Printf("aFunction %d is not recognised \n",aFunction);
+			r=KErrNotSupported;
+			}
+		}
+	return r;
+	}
+
+
+//#if defined(MASTER_MODE) && defined(SLAVE_MODE)
+#endif
+
+
+