--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/iic/iic_psl/i2c.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -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
+
+
+