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