Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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);
}
// 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
{
#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 new DSimulatedI2cDevice;
}
#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