Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test/iic/iic_psl/spi.cpp
18 #ifdef IIC_INSTRUMENTATION_MACRO
19 #include <drivers/iic_trace.h>
22 #define NUM_CHANNELS 4 // Arbitrary
24 // Macros to be updated(?) with interaction with Configuration Repository
25 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMaster};
26 #define CHANNEL_TYPE(n) (KChannelTypeArray[n])
27 const DIicBusChannel::TChannelDuplex KChannelDuplexArray[NUM_CHANNELS] = {DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EFullDuplex};
28 #define CHANNEL_DUPLEX(n) (KChannelDuplexArray[n])
31 #define SPI_PRINT(str) Kern::Printf str
33 #define SPI_PRINT(str)
36 _LIT(KSpiThreadName,"SpiChannelThread");
38 const TInt KSpiThreadPriority = 5; // Arbitrary, can be 0-7, 7 highest
40 #ifdef STANDALONE_CHANNEL
41 _LIT(KPddNameSpi,"spi_ctrless.pdd");
43 _LIT(KPddNameSpi,"spi.pdd");
46 #ifndef STANDALONE_CHANNEL
47 LOCAL_C TInt8 AssignChanNum()
49 static TInt8 iBaseChanNum = KSpiChannelNumBase;
50 SPI_PRINT(("SPI AssignChanNum - on entry, iBaseCanNum = 0x%x\n",iBaseChanNum));
51 return iBaseChanNum++; // Arbitrary, for illustration
55 NONSHARABLE_CLASS(DSimulatedSpiDevice) : public DPhysicalDevice
57 // Class to faciliate loading of the IIC classes
65 DSimulatedSpiDevice();
66 virtual TInt Install();
67 virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
68 virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
69 virtual void GetCaps(TDes8& aDes) const;
70 inline static TVersion VersionRequired();
73 TVersion DSimulatedSpiDevice::VersionRequired()
75 SPI_PRINT(("DSimulatedSpiDevice::VersionRequired\n"));
76 return TVersion(KIicClientMajorVersionNumber,KIicClientMinorVersionNumber,KIicClientBuildVersionNumber);
79 /** Factory class constructor */
80 DSimulatedSpiDevice::DSimulatedSpiDevice()
82 SPI_PRINT(("DSimulatedSpiDevice::DSimulatedSpiDevice\n"));
83 iVersion = DSimulatedSpiDevice::VersionRequired();
86 TInt DSimulatedSpiDevice::Install()
88 SPI_PRINT(("DSimulatedSpiDevice::Install\n"));
89 return(SetName(&KPddNameSpi));
92 /** Called by the kernel's device driver framework to create a Physical Channel. */
93 TInt DSimulatedSpiDevice::Create(DBase*& /*aChannel*/, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
95 SPI_PRINT(("DSimulatedSpiDevice::Create\n"));
99 /** Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
100 TInt DSimulatedSpiDevice::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
102 SPI_PRINT(("DSimulatedSpiDevice::Validate\n"));
103 if (!Kern::QueryVersionSupported(DSimulatedSpiDevice::VersionRequired(),aVer))
104 return(KErrNotSupported);
108 /** Return the driver capabilities */
109 void DSimulatedSpiDevice::GetCaps(TDes8& aDes) const
111 SPI_PRINT(("DSimulatedSpiDevice::GetCaps\n"));
112 // Create a capabilities object
114 caps.iVersion = iVersion;
116 TInt maxLen = aDes.MaxLength();
119 TInt size=sizeof(caps);
122 aDes.Copy((TUint8*)&caps,size);
125 // supported channels for this implementation
126 static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS];
128 //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY)
129 DECLARE_STANDARD_PDD() // SPI test driver to be explicitly loaded as an LDD, not kernel extension
131 SPI_PRINT(("\n\nSPI PDD, channel creation loop follows ...\n"));
133 #ifndef STANDALONE_CHANNEL
134 DIicBusChannel* chan=NULL;
135 for(TInt i=0; i<NUM_CHANNELS; i++)
138 if(CHANNEL_TYPE(i) == (DIicBusChannel::EMaster))
140 chan=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE,CHANNEL_DUPLEX(i));
143 SPI_PRINT(("SPI chan created at 0x%x\n",chan));
144 if(((DSimulatedIicBusChannelMasterSpi*)chan)->Create()!=KErrNone)
147 else if(CHANNEL_TYPE(i) == DIicBusChannel::EMasterSlave)
149 DIicBusChannel* chanM=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE,CHANNEL_DUPLEX(i));
152 DIicBusChannel* chanS=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE,CHANNEL_DUPLEX(i));
155 // For MasterSlave channel, the channel number for both the Master and Slave channels must be the same
156 TInt8 msChanNum = ((DSimulatedIicBusChannelMasterSpi*)chanM)->GetChanNum();
157 ((DSimulatedIicBusChannelSlaveSpi*)chanS)->SetChanNum(msChanNum);
159 chan=new DIicBusChannelMasterSlave(BUS_TYPE,CHANNEL_DUPLEX(i),(DIicBusChannelMaster*)chanM,(DIicBusChannelSlave*)chanS); // Generic implementation
162 SPI_PRINT(("SPI chan created at 0x%x\n",chan));
163 if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
168 chan=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE,CHANNEL_DUPLEX(i));
171 SPI_PRINT(("SPI chan created at 0x%x\n",chan));
172 if(((DSimulatedIicBusChannelSlaveSpi*)chan)->Create()!=KErrNone)
175 ChannelPtrArray[i]=chan;
177 SPI_PRINT(("\nSPI PDD, channel creation loop done- about to invoke RegisterChannels\n\n"));
178 #ifdef IIC_INSTRUMENTATION_MACRO
179 IIC_REGISTERCHANS_START_PSL_TRACE;
183 r=DIicBusController::RegisterChannels(ChannelPtrArray,NUM_CHANNELS);
185 #ifdef IIC_INSTRUMENTATION_MACRO
186 IIC_REGISTERCHANS_END_PSL_TRACE;
188 SPI_PRINT(("\nSPI - returned from RegisterChannels with r=%d\n",r));
195 return new DSimulatedSpiDevice;
198 #ifdef STANDALONE_CHANNEL
201 DSimulatedIicBusChannelMasterSpi::DSimulatedIicBusChannelMasterSpi(const TBusType aBusType, const TChannelDuplex aChanDuplex)
202 : DIicBusChannelMaster(aBusType,aChanDuplex)
204 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DSimulatedIicBusChannelMasterSpi, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex));
205 #ifndef STANDALONE_CHANNEL
206 iChannelNumber = AssignChanNum();
208 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DSimulatedIicBusChannelMasterSpi, iChannelNumber=%d\n",iChannelNumber));
209 iTestState = ETestNone;
210 iChannelState = EIdle;
213 // The time-out call back invoked when the Slave exeecds the allowed response time
214 TInt DSimulatedIicBusChannelMasterSpi::HandleSlaveTimeout()
216 SPI_PRINT(("HandleSlaveTimeout \n"));
217 return AsynchStateMachine(ETimeExpired);
220 TInt DSimulatedIicBusChannelMasterSpi::DoCreate()
222 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoCreate\n"));
223 TInt r=Init(); // PIL Base class initialisation
224 r=Kern::DynamicDfcQCreate(iDynamicDfcQ,KSpiThreadPriority,KSpiThreadName);
226 SetDfcQ((TDfcQue*)iDynamicDfcQ);
227 DSimulatedIicBusChannelMasterSpi::SetRequestDelayed(this,EFalse);
231 TInt DSimulatedIicBusChannelMasterSpi::CheckHdr(TDes8* aHdr)
233 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr\n"));
235 TConfigSpiBufV01* spiBuf = (TConfigSpiBufV01*)aHdr;
236 TConfigSpiV01* spiPtr = &((*spiBuf)());
238 // Valid values for the device ID will depend on the bus configuration
240 // Check that the values for word width, clock speed and clock mode are recognised
241 if((spiPtr->iWordWidth < 0) || (spiPtr->iWordWidth > ESpiWordWidth_16))
243 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr unrecognised word width identifier %d\n",spiPtr->iWordWidth));
246 if(spiPtr->iClkSpeedHz < 0)
248 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr negative clock speed specified %d\n",spiPtr->iClkSpeedHz));
251 if((spiPtr->iClkMode < 0) || (spiPtr->iClkMode > ESpiPolarityHighRisingEdge))
253 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr unrecognised clock mode identifier %d\n",spiPtr->iClkMode));
256 // Values for the timeout period are arbitrary - can only check it is not a negative value
257 if(spiPtr->iTimeoutPeriod < 0)
259 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr negative timeout period %d\n",spiPtr->iTimeoutPeriod));
262 if((spiPtr->iEndianness < 0) || (spiPtr->iEndianness > ELittleEndian))
264 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr unrecognised endianness identifier %d\n",spiPtr->iEndianness));
267 if((spiPtr->iBitOrder < 0) || (spiPtr->iBitOrder > EMsbFirst))
269 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr unrecognised bit order identifier %d\n",spiPtr->iBitOrder));
272 if((spiPtr->iSSPinActiveMode < 0) || (spiPtr->iSSPinActiveMode > ESpiCSPinActiveHigh))
274 SPI_PRINT(("ERROR: DSimulatedIicBusChannelMasterSpi::CheckHdr unrecognised Slave select pin mode identifier %d\n",spiPtr->iSSPinActiveMode));
277 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr word width = %d\n",spiPtr->iWordWidth));
278 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr clock speed = %d\n",spiPtr->iClkSpeedHz));
279 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr clock mode = %d\n",spiPtr->iClkMode));
280 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr timeout period = %d\n",spiPtr->iTimeoutPeriod));
281 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr endianness = %d\n",spiPtr->iEndianness));
282 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr bit order = %d\n",spiPtr->iBitOrder));
283 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr transaction wait cycles = %d\n",spiPtr->iTransactionWaitCycles));
284 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CheckHdr slave select pin mode = %d\n",spiPtr->iSSPinActiveMode));
286 // For the set of tests expecft the following values
287 // ESpiWordWidth_8, 100kHz, ESpiPolarityLowRisingEdge,aTimeoutPeriod=100
288 // EBigEndian, EMsbFirst, 10 wait cycles, Slave select active low
289 if( (spiPtr->iWordWidth != ESpiWordWidth_8) ||
290 (spiPtr->iClkSpeedHz != 100000) ||
291 (spiPtr->iClkMode != ESpiPolarityLowRisingEdge) ||
292 (spiPtr->iTimeoutPeriod != 100) ||
293 (spiPtr->iEndianness != ELittleEndian) ||
294 (spiPtr->iBitOrder != EMsbFirst) ||
295 (spiPtr->iTransactionWaitCycles != 10) ||
296 (spiPtr->iSSPinActiveMode != ESpiCSPinActiveLow) )
301 TInt DSimulatedIicBusChannelMasterSpi::CompareTransactionOne(TIicBusTransaction* aTransaction)
302 // Compares the indicated TIicBusTransaction with the expected content
303 // Returns KErrNone if there is a match, KErrCorrupt otherwise.
306 // Check the transaction header
307 // Should contain the default header for SPI
308 TDes8* bufPtr = GetTransactionHeader(aTransaction);
311 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - NULL header\n"));
314 TConfigSpiV01 *buf = (TConfigSpiV01 *)(bufPtr->Ptr());
315 if(buf->iWordWidth != ESpiWordWidth_8)
317 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - Header wordwidth mis-match\n"));
320 if(buf->iClkSpeedHz !=100000)
322 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - Header clockspeed mis-match\n"));
325 if(buf->iClkMode != ESpiPolarityLowRisingEdge)
327 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - Header polarity mis-match\n"));
330 if(buf->iTimeoutPeriod != 100)
332 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - Header timeout mis-match\n"));
336 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne header OK\n"));
338 // Check the half-duplex transfer list
339 TIicBusTransfer* tfer = GetTransHalfDuplexTferPtr(aTransaction);
342 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - NULL half-duplex transfer\n"));
345 // Process each transfer in the list
348 // tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
349 // buf1 contains copy of TUint8 KTransOneTferOne[21] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
350 dummy=GetTferType(tfer);
351 if(dummy!=TIicBusTransfer::EMasterWrite)
353 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer1 type=%d\n"));
356 dummy=GetTferBufGranularity(tfer);
359 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer1 granularity=%d\n",dummy));
362 if((bufPtr = (TDes8*)GetTferBuffer(tfer)) == NULL)
364 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer1 buffer NULL\n"));
371 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR tfer1 buffer element %d has 0x%x\n",i,(*bufPtr)[i]));
375 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne tfer1 OK\n"));
378 tfer=GetTferNextTfer(tfer);
379 // tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterRead,8,buf2);
380 // buf2 contains copy of TUint8 KTransOneTferTwo[8] = {17,18,19,20,21,22,23,24};
381 dummy=GetTferType(tfer);
382 if(dummy!=TIicBusTransfer::EMasterRead)
384 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer2 type=%d\n",dummy));
387 dummy=GetTferBufGranularity(tfer);
390 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer2 granularity=%d\n",dummy));
393 if((bufPtr = (TDes8*)GetTferBuffer(tfer)) == NULL)
395 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer2 buffer NULL\n"));
400 if((*bufPtr)[i]!=(17+i))
402 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR tfer2 buffer element %d has 0x%x\n",i,(*bufPtr)[i]));
406 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne tfer2 OK\n"));
408 tfer=GetTferNextTfer(tfer);
409 // tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
410 // buf2 contains copy of TUint8 KTransOneTferThree[6] = {87,85,83,81,79,77};
411 dummy=GetTferType(tfer);
412 if(dummy!=TIicBusTransfer::EMasterWrite)
414 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer3 type=%d\n"));
417 dummy=GetTferBufGranularity(tfer);
420 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer3 granularity=%d\n",dummy));
423 if((bufPtr = (TDes8*)GetTferBuffer(tfer)) == NULL)
425 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer3 buffer NULL\n"));
430 if((*bufPtr)[i]!=(87-(2*i)))
432 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR tfer3 buffer element %d has 0x%x\n",i,(*bufPtr)[i]));
436 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne tfer3 OK\n"));
438 // Shouldn't be any more transfers in the half duplex list
439 if((tfer=GetTferNextTfer(tfer))!=NULL)
441 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - tfer3 iNext=0x%x\n",tfer));
444 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne half-duplex transfer OK\n"));
446 // The full duplex transfer should be represented by a NULL pointer
447 if((tfer=GetTransFullDuplexTferPtr(aTransaction))!=NULL)
449 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - full duplex pointer=0x%x\n",tfer));
452 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne full duplex pointer is NULL (OK)\n"));
454 // Synchronous transaction, so check the callback pointer is NULL
455 TIicBusCallback* dumCb = NULL;
456 dumCb=GetTransCallback(aTransaction);
459 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - callback pointer=0x%x\n",dumCb));
462 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne callback pointer is NULL (OK)\n"));
464 // Check the transaction flags are set to zero
466 dumFlags=GetTransFlags(aTransaction);
469 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne ERROR - flags=0x%x\n",dumFlags));
472 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::CompareTransactionOne flags are zero (OK)\n"));
478 // The THwCallbackFunc gets called if the hardware preparation completes successfully.
479 void THwCallbackFunc(TAny* aPtr)
481 SPI_PRINT(("Hardware preparation completed, calling the callback function"));
482 DSimulatedIicBusChannelMasterSpi* aChanMasterSpi=(DSimulatedIicBusChannelMasterSpi* )aPtr;
483 TInt r = aChanMasterSpi->DoSimulatedTransaction();
484 ((DSimulatedIicBusChannelMasterSpi*)aChanMasterSpi)->CompleteReq(r);
487 TInt DSimulatedIicBusChannelMasterSpi::DoSimulatedTransaction()
489 TInt r = AsynchStateMachine(EHwTransferDone);
490 if(iTimeoutTimer.Cancel() == FALSE)
492 SPI_PRINT(("timer is not cancelled"));
497 TInt DSimulatedIicBusChannelMasterSpi::DoHwPreparation()
499 SPI_PRINT(("Preparing hardware for the transaction"));
502 // The hardware preparation can either complete successfully or fail.
503 // If successful, invoke the callback function of THwDoneCallBack
504 // if not, execute the timeout machanism
505 // Currently DoHwPreparation is just a simple function. It should be more complicated
506 // for the real hardware.
509 case (ETestSlaveTimeOut):
511 // In the timeout test, do nothing until the timeout callback function is invoked.
512 SPI_PRINT(("Simulating the timeout process."));
517 // Pretend the hardware preparation's been done, and a callback function is invoked to call
518 // the Asynchronous State Machine
519 SPI_PRINT(("Hardware preparing work is executing normally."));
525 SPI_PRINT(("Not a valid test."));
526 r = KErrNotSupported;
534 // Gateway function for PSL implementation, invoked for DFC processing
535 TInt DSimulatedIicBusChannelMasterSpi::DoRequest(TIicBusTransaction* aTransaction)
537 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest invoked with aTransaction=0x%x\n",aTransaction));
540 iCurrTrans=aTransaction;
542 // Check if the Asynchronous State Machine is available. If not, then return KErrInUse.
543 // This is used to stop the second transaction executing if the machine has already been holding
544 // by a transaction. However, this situation cannot be tested because of the malfunction in PIL
545 if(iChannelState!= EIdle)
548 iChannelState = EBusy;
549 #ifdef IIC_INSTRUMENTATION_MACRO
550 IIC_MPROCESSTRANS_START_PSL_TRACE;
552 r = ProcessTrans(aTransaction);
554 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest - exiting\n"));
558 TInt DSimulatedIicBusChannelMasterSpi::ProcessTrans(TIicBusTransaction* aTransaction)
564 case(ETestWaitTransOne):
566 // The transaction received should exhibit the expected data
567 // Return KErrArgument if this is not the case
568 // The timer should be started at the beginning of every transaction
569 // For simplicity, we omit the timer here.
570 r=CompareTransactionOne(iCurrTrans);
571 iChannelState = EIdle;
572 CompleteRequest(KErrNone);
575 case(ETestSlaveTimeOut):
577 // Test the timeout funciton
578 SPI_PRINT(("Test the slave timeout function\n"));
580 // Simulate a timeout
581 // Start a timer and then wait for the Slave response to timeout
582 // A real bus would use its own means to identify a timeout
583 TInt aTime=1000000/NKern::TickPeriod();
584 r = StartSlaveTimeOutTimer(aTime);
587 r = DoHwPreparation();
590 case(ETestWaitPriorityTest):
592 static TInt TranCount = 0;
593 if(TranCount >= KPriorityTestNum) return KErrUnknown;
595 while(IsRequestDelayed(this))
597 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest - starting Sleep...\n"));
598 NKern::Sleep(1000); // 1000 is arbitrary
599 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest - completed Sleep, check if still delayed\n"));
601 // get transaction header
602 TDes8* bufPtr = GetTransactionHeader(aTransaction);
605 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest ERROR - NULL header\n"));
611 // ignore the blocking transaction
616 // store transaction header
617 iPriorityTestResult[TranCount++] = (*bufPtr)[0];
618 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::DoRequest Priority test transaction no.:%d Priority:%d",
619 (*bufPtr)[0], aTransaction->iKey));
621 iChannelState = EIdle;
622 CompleteRequest(KErrNone);
623 if(TranCount == KPriorityTestNum) iPriorityTestDone = ETrue;
631 SPI_PRINT(("Nothing to be tested, just do the usual transaction"));
633 // Start the timer on the Slave response.
634 // Since no timeout, this timer will be cancelled in the THwCallbackFunc
635 r = StartSlaveTimeOutTimer(100000);
638 // Use a class THwDoneCallBack derived from TDfc to trigger the asynchronous state machine
639 // when the hardware preparation completes successfully.
640 // The priority is set with an arbitrary number 5
641 iCb = new THwDoneCallBack(THwCallbackFunc, this, iDynamicDfcQ, 5);
642 r = DoHwPreparation();
647 SPI_PRINT(("Test status not matched"));
648 return KErrNotSupported;
656 TInt DSimulatedIicBusChannelMasterSpi::AsynchStateMachine(TInt aReason)
660 // The asynchronous state machine has two states, it could either be idle or busy.
661 // Initially, it's in idle state. When a user queues a transaction, the hardware preparation starts
662 // and the state changes to busy. After the hardware preparation completes, either successfully or not,
663 // the state machine will do the corresponding work for the transaction and then goes back to the idle state.
664 switch(iChannelState)
674 case(EHwTransferDone):
677 // Simulate processing - for now, do nothing!
679 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine aTransaction->iHeader=0x%x\n",GetTransactionHeader(iCurrTrans)));
680 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine aTransaction->iHalfDuplexTrans=0x%x\n",GetTransHalfDuplexTferPtr(iCurrTrans)));
681 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine aTransaction->iFullDuplexTrans=0x%x\n",GetTransFullDuplexTferPtr(iCurrTrans)));
682 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine aTransaction->iCallback=0x%x\n",GetTransCallback(iCurrTrans)));
683 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine aTransaction->iFlags=0x%x\n",GetTransFlags(iCurrTrans)));
685 SPI_PRINT(("\nDSimulatedIicBusChannelMasterSpi::AsynchStateMachine, iHeader info \n"));
686 TDes8* bufPtr = GetTransactionHeader(iCurrTrans);
689 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine ERROR - NULL header\n"));
692 TConfigSpiV01 *buf = (TConfigSpiV01 *)(bufPtr->Ptr());
693 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header word width=0x%x\n",buf->iWordWidth));
694 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header clock speed=0x%x\n",buf->iClkSpeedHz));
695 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header clock mode=0x%x\n",buf->iClkMode));
696 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header timeout period=0x%x\n",buf->iTimeoutPeriod));
697 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header endianness=0x%x\n",buf->iEndianness));
698 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header bit order=0x%x\n",buf->iBitOrder));
699 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header wait cycles=0x%x\n",buf->iTransactionWaitCycles));
700 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine, header Slave select pin mode=0x%x\n",buf->iSSPinActiveMode));
701 (void)buf; // Silence compiler when SPI_PRINT not used
703 SPI_PRINT(("\nDSimulatedIicBusChannelMasterSpi::AsynchStateMachine, iHalfDuplexTrans info \n"));
704 TIicBusTransfer* halfDuplexPtr=GetTransHalfDuplexTferPtr(iCurrTrans);
705 while(halfDuplexPtr != NULL)
707 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine transfer type=0x%x\n",GetTferType(halfDuplexPtr)));
708 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine granularity=0x%x\n",GetTferBufGranularity(halfDuplexPtr)));
709 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine transfer buffer=0x%x\n",GetTferBuffer(halfDuplexPtr)));
710 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine next transfer =0x%x\n",GetTferNextTfer(halfDuplexPtr)));
711 halfDuplexPtr=GetTferNextTfer(halfDuplexPtr);
713 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine - End of iHalfDuplexTrans info"));
715 while(IsRequestDelayed(this))
717 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine - starting Sleep...\n"));
718 NKern::Sleep(1000); // 1000 is arbitrary
719 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::AsynchStateMachine - completed Sleep, check if still delayed\n"));
728 SPI_PRINT(("Time expired, the Asynchrnous State Machine will be Idle again, and wait for the next request."));
735 SPI_PRINT(("Request can not be handled, return error code."));
736 return KErrNotSupported;
743 SPI_PRINT(("No matched state"));
751 TBool DSimulatedIicBusChannelMasterSpi::IsRequestDelayed(DSimulatedIicBusChannelMasterSpi* aChan)
753 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::IsRequestDelayed invoked for aChan=0x%x\n",aChan));
754 return aChan->iReqDelayed;
757 void DSimulatedIicBusChannelMasterSpi::SetRequestDelayed(DSimulatedIicBusChannelMasterSpi* aChan,TBool aDelay)
759 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::SetRequestDelayed invoked for aChan=0x%x, with aDelay=0x%d\n",aChan,aDelay));
760 aChan->iReqDelayed=aDelay;
763 TInt DSimulatedIicBusChannelMasterSpi::StaticExtension(TUint aFunction, TAny* aParam1, TAny* aParam2)
765 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::StaticExtension\n"));
766 #ifdef IIC_INSTRUMENTATION_MACRO
767 IIC_MSTATEXT_START_PSL_TRACE;
772 // Test values of aFunction were shifted left one place by the (test) client driver
773 // and for Slave values the two msb were cleared
774 // Return to its original value.
775 if(aFunction>KTestControlIoPilOffset)
779 case(RBusDevIicClient::ECtlIoDumpChan):
786 case(RBusDevIicClient::ECtlIoBlockReqCompletion):
788 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::Blocking request completion\n"));
789 SetRequestDelayed(this, ETrue);
792 case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
794 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi::Unlocking request completion\n"));
795 SetRequestDelayed(this, EFalse);
798 case(RBusDevIicClient::ECtlIoDeRegChan):
800 #ifdef IIC_INSTRUMENTATION_MACRO
801 IIC_DEREGISTERCHAN_START_PSL_TRACE;
803 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: deregister channel\n"));
804 #ifndef STANDALONE_CHANNEL
805 r=DIicBusController::DeRegisterChannel(this);
808 #ifdef IIC_INSTRUMENTATION_MACRO
809 IIC_DEREGISTERCHAN_END_PSL_TRACE;
814 case(RBusDevIicClient::ECtlIoPriorityTest):
816 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: warned to expect priority test\n"));
817 iPriorityTestDone = EFalse;
818 iTestState=ETestWaitPriorityTest;
821 case(RBusDevIicClient::EGetTestResult):
823 if(!iPriorityTestDone) return KErrNotReady;
825 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: get priority test order\n"));
827 //iPriorityTestResult[0] is the blocking transaction, ignore it. start from entry 1.
828 for(TInt i=1; i<KPriorityTestNum; i++)
830 if(iPriorityTestResult[i]!=(KPriorityTestNum-i-1))
840 case(RBusDevIicClient::ECtlIoTracnOne):
842 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: warned to expect Transaction One\n"));
843 iTestState=ETestWaitTransOne;
846 case(RBusDevIicClient::ECtlIoNone):
848 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: terminate ControlIO state\n"));
849 iTestState=ETestNone;
852 case(RBusDevIicClient::ECtlIoSetTimeOutFlag):
854 SPI_PRINT(("DSimulatedIicBusChannelMasterSpi: test slave time out\n"));
855 iTestState=ETestSlaveTimeOut;
860 Kern::Printf("aFunction %d is not recognised \n",aFunction);
864 #ifdef IIC_INSTRUMENTATION_MACRO
865 IIC_MSTATEXT_END_PSL_TRACE;
870 void DSimulatedIicBusChannelMasterSpi::CompleteReq(TInt aResult)
872 #ifdef IIC_INSTRUMENTATION_MACRO
873 IIC_MPROCESSTRANS_END_PSL_TRACE;
875 CompleteRequest(aResult);
879 void DSimulatedIicBusChannelSlaveSpi::SlaveAsyncSimCallback(TAny* aPtr)
881 SPI_PRINT(("SlaveAsyncSimCallback\n"));
882 DSimulatedIicBusChannelSlaveSpi* channel = (DSimulatedIicBusChannelSlaveSpi*)aPtr;
883 TInt r=KErrNone; // Just simulate successfull capture
884 #ifdef IIC_INSTRUMENTATION_MACRO
885 IIC_SCAPTCHANASYNC_END_PSL_TRACE;
887 channel->ChanCaptureCb(r);
890 #ifdef STANDALONE_CHANNEL
893 DSimulatedIicBusChannelSlaveSpi::DSimulatedIicBusChannelSlaveSpi(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex)
894 : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class
895 iSlaveTimer(SlaveAsyncSimCallback,this)
897 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::DSimulatedIicBusChannelSlaveSpi, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex));
898 #ifndef STANDALONE_CHANNEL
899 iChannelNumber = AssignChanNum();
901 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::DSimulatedIicBusChannelSlaveSpi, iChannelNumber=%d\n",iChannelNumber));
904 TInt DSimulatedIicBusChannelSlaveSpi::CaptureChannelPsl(TDes8* /*aConfigHdr*/, TBool aAsynch)
906 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::CaptureChannelPsl, aAsynch=%d\n",aAsynch));
910 #ifdef IIC_INSTRUMENTATION_MACRO
911 IIC_SCAPTCHANASYNC_START_PSL_TRACE;
913 // To simulate an asynchronous operation, just set a timer to expire
914 iSlaveTimer.OneShot(1000, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1
918 #ifdef IIC_INSTRUMENTATION_MACRO
919 IIC_SCAPTCHANSYNC_START_PSL_TRACE;
921 // PSL processing would happen here ...
922 // Expected to include implementation of the header configuration information
923 #ifdef IIC_INSTRUMENTATION_MACRO
924 IIC_SCAPTCHANSYNC_END_PSL_TRACE;
927 SPI_PRINT(("DSimulatedIicBusChannelSlaveI2c::CaptureChanSync ... no real processing to do \n"));
932 TInt DSimulatedIicBusChannelSlaveSpi::CheckHdr(TDes8* /*aHdr*/)
934 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::CheckHdr\n"));
938 TInt DSimulatedIicBusChannelSlaveSpi::DoCreate()
940 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::DoCreate\n"));
941 TInt r=Init(); // PIL Base class initialisation
945 TInt DSimulatedIicBusChannelSlaveSpi::DoRequest(TInt /*aTrigger*/)
947 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::DoRequest\n"));
948 return KErrNotSupported;
951 void DSimulatedIicBusChannelSlaveSpi::ProcessData(TInt /*aTrigger*/, TIicBusSlaveCallback* /*aCb*/)
953 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::ProcessData\n"));
956 TInt DSimulatedIicBusChannelSlaveSpi::StaticExtension(TUint aFunction, TAny* aParam1, TAny* aParam2)
958 SPI_PRINT(("DSimulatedIicBusChannelSlaveSpi::StaticExtension\n"));
959 #ifdef IIC_INSTRUMENTATION_MACRO
960 IIC_SSTATEXT_START_PSL_TRACE;
964 // Test values of aFunction were shifted left one place by the (test) client driver
965 // and for Slave values the two msb were cleared
966 // Return to its original value.
967 if(aFunction>KTestControlIoPilOffset)
969 aFunction |= 0xC0000000;
975 case(RBusDevIicClient::ECtlIoDumpChan):
984 Kern::Printf("aFunction %d is not recognised \n",aFunction);
989 #ifdef IIC_INSTRUMENTATION_MACRO
990 IIC_SSTATEXT_START_PSL_TRACE;