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_client.cpp
15 // Simulated (kernel-side) client of IIC Platform Independent Layer (PIL)
17 #include <kernel/kern_priv.h> // for DThread, TDfc
18 #ifdef STANDALONE_CHANNEL
19 #include <drivers/iic_transaction.h>
21 #include <drivers/iic.h>
24 #ifdef STANDALONE_CHANNEL
25 #include <drivers/iic_channel.h>
31 #define CLIENT_PRINT(str) Kern::Printf str
33 #define CLIENT_PRINT(str)
36 const TInt KIicClientThreadPriority = 24;
37 const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest ... for MasterSlave functionality
39 const TInt KMaxNumChannels = 3; // 1 SPI and 2 I2C
41 // Define an array of channel that the client is going to create.
42 // For iic_client, it needs SPI channels for Master tests, and I2c channels for MasterSlave tests.
43 #ifdef STANDALONE_CHANNEL
45 const TUint NUM_CHANNELS_SPI = 4; // Arbitrary
46 const TInt KChannelTypeArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMaster};
47 #define CHANNEL_TYPE_SPI(n) (KChannelTypeArraySpi[n])
48 const DIicBusChannel::TChannelDuplex KChannelDuplexArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EFullDuplex};
49 #define CHANNEL_DUPLEX_SPI(n) (KChannelDuplexArraySpi[n])
50 #define BUS_TYPE_SPI (DIicBusChannel::ESpi)
52 #define NUM_CHANNELS_I2C 3
53 #if defined(MASTER_MODE) && !defined(SLAVE_MODE)
54 const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
55 #elif defined(MASTER_MODE) && defined(SLAVE_MODE)
56 const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
58 const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
60 #define CHANNEL_TYPE_I2C(n) (KChannelTypeArrayI2c[n])
61 #define CHANNEL_DUPLEX_I2C(n) (DIicBusChannel::EHalfDuplex)
62 #define BUS_TYPE_I2C (DIicBusChannel::EI2c)
64 const TInt8 KSpiChannelNumBase = 1; // Arbitrary, real platform may consult the Configuration Repository
65 // Note limit of 5 bit representation (0-31)
67 LOCAL_C TInt8 AssignChanNumSpi()
69 static TInt8 iBaseChanNumSpi = KSpiChannelNumBase;
70 CLIENT_PRINT(("SPI AssignChanNum - on entry, iBaseCanNum = 0x%x\n",iBaseChanNumSpi));
71 return iBaseChanNumSpi++; // Arbitrary, for illustration
74 #if defined(MASTER_MODE)
75 const TInt8 KI2cChannelNumBase = 10; // Arbitrary, real platform may consult the Configuration Repository
76 // Note limit of 5 bit representation (0-31)
79 const TInt8 KI2cChannelNumBase = 10 + NUM_CHANNELS; // For Slave mode, want to provide different response
80 // If client assumes Master mode, should be informed not available
83 LOCAL_C TInt8 AssignChanNumI2c()
85 static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
86 CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
87 return iBaseChanNumI2c++; // Arbitrary, for illustration
90 class DIicClientChan : public DBase
93 DIicClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TUint8 aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
95 TInt GetChanNum()const {return iChanNumber;};
96 TUint8 GetChanType()const {return iChanType;};
97 DIicBusChannel* GetChannelPtr(){return iChan;};
98 inline DIicClientChan& operator=(DIicClientChan& aChan) {iChanNumber=aChan.iChanNumber; iChanType=aChan.iChanType; iChan=aChan.iChan; return *this;};
99 inline TInt operator==(DIicClientChan& aChan) {if((iChanNumber == aChan.iChanNumber)&&(iChanType == aChan.iChanType)&&(iChan == aChan.iChan)) return 1;return 0;};
103 DIicBusChannel* iChan;
106 DIicClientChan::~DIicClientChan()
111 #endif /*STANDALONE_CHANNEL*/
114 #ifdef STANDALONE_CHANNEL
115 _LIT(KLddRootName,"iic_client_ctrless");
117 _LIT(KLddRootName,"iic_client");
119 _LIT(KIicClientThreadName,"IicClientLddThread");
121 struct TCapsIicClient
126 struct TTransStatusPair
128 TRequestStatus* iReq;
129 TIicBusTransaction* iTrans;
134 TIicBusTransaction* iTrans;
135 TIicBusCallback* iCb;
140 TExtractInfo(){iBufPtr = NULL; iTfer = NULL;}
141 ~TExtractInfo(){delete iBufPtr; delete iTfer;}
143 TIicBusTransfer* iTfer;
144 TIicBusTransaction* iTrans;
147 struct TTransBufReuseData
149 // Convenience for testing, only - retain pointers to private data
150 // so that it can be re-used from a callback.
151 TIicBusTransaction* iTransaction;
152 TIicBusTransfer* iHdTfer;
153 TIicBusTransfer* iFdTfer;
155 // Pointer to callback object (for cleanup)
156 TIicBusCallback* iCallback;
159 class DDeviceIicClient : public DLogicalDevice
171 * Second stage constructor - install the device
173 virtual TInt Install();
175 * Get the Capabilites of the device
176 * @param aDes descriptor that will contain the returned capibilites
178 virtual void GetCaps(TDes8 &aDes) const;
180 * Create a logical channel to the device
182 virtual TInt Create(DLogicalChannelBase*& aChannel);
187 #ifdef STANDALONE_CHANNEL
188 /*This class is used to test the set and get inline functions
189 * of DIicBusChannel Interface.
191 class TTestIicChannelInterface: public DIicBusChannel
194 TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex);
195 ~TTestIicChannelInterface(){};
196 TInt DoCreate(){return 0;};
197 TInt CheckHdr(TDes8* /*aHdr*/){return 0;};
198 TInt TestInterface();
200 TBool TestChannelType(DIicBusChannel::TChannelType aType );
201 TBool TestBusType(DIicBusChannel::TBusType aType );
202 TBool TestDuplexType(DIicBusChannel::TChannelDuplex aType );
205 TTestIicChannelInterface::TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex)
206 : DIicBusChannel(aChannelType, aBusType, aChanDuplex)
209 TBool TTestIicChannelInterface::TestChannelType(DIicBusChannel::TChannelType aType)
211 CLIENT_PRINT(("Setting channel type 0x%x\n", aType));
212 SetChannelType(aType);
213 if(aType != ChannelType())
215 CLIENT_PRINT(("ERROR: Mismatch, looking for channel 0x%x but found 0x%x\n", aType, ChannelType()));
220 CLIENT_PRINT(("Looking for channel 0x%x and found 0x%x\n", aType, ChannelType()));
225 TBool TTestIicChannelInterface::TestBusType(DIicBusChannel::TBusType aType)
227 CLIENT_PRINT(("Setting Bus type 0x%x\n", aType));
229 if(aType != BusType())
231 CLIENT_PRINT(("ERROR: Mismatch, looking for Bus 0x%x but found 0x%x\n", aType, BusType()));
236 CLIENT_PRINT(("Looking for Bus 0x%x and found 0x%x\n", aType, BusType()));
241 TBool TTestIicChannelInterface::TestDuplexType(DIicBusChannel::TChannelDuplex aType)
243 CLIENT_PRINT(("Setting duplex channel type 0x%x\n", aType));
244 SetChannelType(aType);
245 if(aType != ChannelDuplex())
247 CLIENT_PRINT(("ERROR: Mismatch, looking for duplex channel 0x%x but found 0x%x\n", aType, ChannelDuplex()));
252 CLIENT_PRINT(("Looking for Duplex Channel 0x%x and found 0x%x\n", aType, ChannelDuplex()));
257 TInt TTestIicChannelInterface::TestInterface()
260 RArray <DIicBusChannel::TChannelType> chtype;
261 RArray <DIicBusChannel::TBusType> bustype;
262 RArray <DIicBusChannel::TChannelDuplex> dutype;
264 chtype.Append(DIicBusChannel::EMaster);
265 chtype.Append(DIicBusChannel::ESlave);
266 chtype.Append(DIicBusChannel::EMasterSlave);
268 bustype.Append(DIicBusChannel::EI2c);
269 bustype.Append(DIicBusChannel::ESpi);
270 bustype.Append(DIicBusChannel::EMicrowire);
271 bustype.Append(DIicBusChannel::ECci);
272 bustype.Append(DIicBusChannel::ESccb);
274 dutype.Append(DIicBusChannel::EHalfDuplex);
275 dutype.Append(DIicBusChannel::EFullDuplex);
277 int result = KErrNone;
278 int count = chtype.Count();
281 CLIENT_PRINT(("\nCheck Master/Slave channel setting\n"));
282 CLIENT_PRINT(("\nChannel MASK = 0x%x\n", KChannelTypeMask));
283 for(i=0; i< count; ++i)
285 if(!TestChannelType(chtype[i]))
287 result = KErrGeneral;
291 CLIENT_PRINT(("\nCheck Master/Slave channel setting from higher bit number to lower, reverse enum.\n"));
292 for(i=count-1; i >= 0; --i)
294 if(!TestChannelType(chtype[i]))
296 result = KErrGeneral;
301 CLIENT_PRINT(("\nCheck Channel Bus type settings\n"));
302 CLIENT_PRINT(("\nBus MASK = 0x%x\n", KBusTypeMask));
303 count = bustype.Count();
304 for(i=0; i< count; ++i)
306 if(!TestBusType(bustype[i]))
308 result = KErrGeneral;
312 CLIENT_PRINT(("\nCheck Channel Bus type settings from higher bit number to lower, reverse enum.\n"));
313 for(i = count-1; i >= 0; --i)
315 if(!TestBusType(bustype[i]))
317 result = KErrGeneral;
321 CLIENT_PRINT(("\nCheck Channel Duplex settings\n"));
322 CLIENT_PRINT(("\nDuplex MASK = 0x%x\n", KChannelDuplexMask));
323 count = dutype.Count();
324 for(i=0; i < count; ++i)
326 if(!TestDuplexType(dutype[i]))
328 result = KErrGeneral;
332 CLIENT_PRINT(("\nCheck Channel Duplex setting from higher bit number to lower, reverse enum.\n"));
333 for(i = count-1; i >= 0; --i)
335 if(!TestDuplexType(dutype[i]))
337 result = KErrGeneral;
346 #endif //STANDALONE_CHANNEL
348 class DChannelIicClient : public DLogicalChannel
352 ~DChannelIicClient();
354 TInt CleanupExtractTrans(TIicBusTransaction *aTrans);
356 TInt InitIicClient();
358 virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
361 virtual void HandleMsg(TMessageBase* aMsg); // Note: this is a pure virtual in DLogicalChannel
363 void DoCancel(TInt aMask); // Name for convenience!
364 TInt DoControl(TInt aId, TAny* a1, TAny* a2); // Name for convenience!
365 TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); // Name for convenience!
367 void TestTransModification(TIicBusTransaction* aTransaction, // public to be accessed by callback
368 TIicBusTransfer* aHdTfer,
369 TIicBusTransfer* aFdTfer,
371 #ifdef STANDALONE_CHANNEL
373 static TInt OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry);
376 TInt ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans);
377 TInt CreateTransferListHalfDuplex(
378 TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
379 TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
380 TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
381 TInt CreateTransferListFullDuplex(
382 TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
383 TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
384 TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
387 TInt DeleteFullDuplexTest(TIicBusTransaction *aTrans);
389 TInt DoCreateFullDuplexTransTest(TInt aTestType);
391 TInt DoPriorityTest(TInt aBusId);
392 TInt ConstructTransactionOne(TIicBusTransaction*& aTrans);
393 void CleanupTransactionOne(TIicBusTransaction*& aTrans);
396 TInt InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair);
398 TInt CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf);
400 //Add new functions for controller-less mode
401 TInt QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback=NULL);
402 TInt CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction);
403 TInt StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2);
404 TInt CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch=NULL);
405 TInt ReleaseChannel(TInt aChannelId);
407 inline void Lock() {Kern::MutexWait(*iArrayMutex);}
408 inline void Unlock() {Kern::MutexSignal(*iArrayMutex);}
409 inline void GetWriteAccess() {Kern::SemaphoreWait(*iChanArrWrtSem);} // aNTicks not specified = wait forever
410 inline void FreeWriteAccess() {Kern::SemaphoreSignal(*iChanArrWrtSem);}
412 void CleanupTransaction(TIicBusTransaction*& aTrans); // public for access by callback
414 static TIicBusTransaction* MultiTranscCallbackFunc(TIicBusTransaction* aTrans, TAny* aParam);
416 static void TransModifCallback(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam);
419 TDynamicDfcQue* iDfcQue;
421 DMutex* iArrayMutex; // used to protect array of channels
422 DSemaphore* iChanArrWrtSem; // used to synchronise write access to iChannelArray
424 // Used for Transaction One
431 TIicBusTransfer* tfer1;
432 TIicBusTransfer* tfer2;
433 TIicBusTransfer* tfer3;
434 TIicBusTransfer* tfer4;
435 TIicBusTransfer* tfer5;
436 TIicBusTransfer* tfer6;
437 TIicBusTransfer* tfer7;
444 TConfigSpiBufV01* spiHeader;
447 static TIicBusTransaction* iMultiTransac;
449 // Used for simple transactions
450 TIicBusTransaction* iTrans;
451 TConfigSpiBufV01* iSpiBuf;
452 TConfigI2cBufV01* iI2cBuf;
453 TIicBusTransfer* iTfer;
454 TIicBusTransactionPreamble* iTransPreamble;
455 TIicBusTransfer* iFdTfer;
459 RPointerArray<TTransStatusPair> iTransStatArrayByTrans;
460 RPointerArray<TTransStatusPair> iTransStatArrayByStatus;
461 RPointerArray<TTransCbPair> iTransCbArrayByTrans;
462 RPointerArray<TExtractInfo> iExtractInfoArray;
464 // Support for Preamble testing
465 TRequestStatus* iPreambleStatus;
466 TRequestStatus* iMultiTranscStatus;
468 // Support for buffer re-use testing
469 TTransBufReuseData iTransBufReuseData;
471 // Support for MasterSlave processing
473 TInt InitSlaveClient();
477 TRequestStatus* iStatus;
480 void RequestComplete(TInt r);
483 TIicBusSlaveCallback* iNotif; // public to be accessible by callback
484 TInt iChannelId; // public to be accessible by callback
487 #ifdef STANDALONE_CHANNEL
488 //Used to store the captured channel
489 struct TCapturedChannel
491 DIicClientChan* iChanPtr;
494 TCapturedChannel iCapturedChannel;
498 DDeviceIicClient::DDeviceIicClient()
501 CLIENT_PRINT(("> DDeviceIicClient::DDeviceIicClient()"));
502 __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::DDeviceIicClient()"));
503 iParseMask=0; // No info, no PDD, no Units
505 iVersion=TVersion(KIicClientMajorVersionNumber,
506 KIicClientMinorVersionNumber,
507 KIicClientBuildVersionNumber);
509 #ifdef STANDALONE_CHANNEL
510 // auxiliary function for ordering entries in the array of channels
511 TInt DChannelIicClient::OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry)
513 TUint8 l=(TUint8)aMatch.GetChanNum();
514 TUint8 r=(TUint8)aEntry.GetChanNum();
522 // global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
523 TLinearOrder<DIicClientChan> EntryOrder(DChannelIicClient::OrderEntries);
525 // Store all the channels created by the client
526 RPointerArray<DIicClientChan> ChannelArray;
527 #endif /*STANDALONE_CHANNEL*/
529 DDeviceIicClient::~DDeviceIicClient()
531 CLIENT_PRINT(("> DDeviceIicClient::~DDeviceIicClient()"));
532 __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::~DDeviceIicClient()"));
533 #ifdef STANDALONE_CHANNEL
534 //For Standalone Channel, the client is responsible for channel destroy
535 ChannelArray.ResetAndDestroy();
539 TInt DDeviceIicClient::Install()
540 // Install the device driver.
542 CLIENT_PRINT(("> DDeviceIicClient::Install()"));
543 __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::Install()"));
544 return(SetName(&KLddRootName));
547 // Auxiliary functions for ordering entries in the array of TTransStatusPair pointers
548 // The first is to enable searching by Transaction (used by the callback)
549 // The second is to enable searching by the TRequestStatus (used by cancel calls)
550 TInt OrderEntriesByTrans(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
552 TUint l=(TUint)(aMatch.iTrans);
553 TUint r=(TUint)(aEntry.iTrans);
561 TLinearOrder<TTransStatusPair> TransStatusOrderByTrans(OrderEntriesByTrans);
563 TInt OrderEntriesByStatus(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
565 TUint l=(TUint)(aMatch.iReq);
566 TUint r=(TUint)(aEntry.iReq);
574 TLinearOrder<TTransStatusPair> TransStatusOrderByStatus(OrderEntriesByStatus);
576 // Auxilliary function to track callback objects assigned to asynchronous transactions
577 TInt OrderCbEntriesByTrans(const TTransCbPair& aMatch, const TTransCbPair& aEntry)
579 TUint l=(TUint)(aMatch.iTrans);
580 TUint r=(TUint)(aEntry.iTrans);
588 TLinearOrder<TTransCbPair> TransCbOrderByTrans(OrderCbEntriesByTrans);
590 TInt OrderExtractInfoByTrans(const TExtractInfo& aMatch, const TExtractInfo& aEntry)
592 TUint l=(TUint)(aMatch.iTrans);
593 TUint r=(TUint)(aEntry.iTrans);
601 TLinearOrder<TExtractInfo> ExtractInfoOrderByTrans(OrderExtractInfoByTrans);
604 _LIT(KLitArrayMutexName,"IIC_CLIENT_ARRAY_MUTEX");
605 _LIT(KLitArraySemName,"IIC_CLIENT_ARRAY_SEM");
606 #define IIC_CLIENT_MUTEX_ORDER KMutexOrdGeneral4 // Semi-arbitrary - middle of general purpose range, allow higher and lower priorities
608 TInt DChannelIicClient::InitIicClient()
610 TInt r = Kern::MutexCreate(iArrayMutex,KLitArrayMutexName,IIC_CLIENT_MUTEX_ORDER);
613 r = Kern::SemaphoreCreate(iChanArrWrtSem,KLitArraySemName,1); // Initial count of one allows first wait to be non-blocking
615 iArrayMutex->Close(NULL);
620 TInt DChannelIicClient::InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair)
622 CLIENT_PRINT(("DChannelIicClient::InsertPairs invoked with aPair=0x%x, aPair->iReq=0x%x, aPair-iTrans=0x%x\n",aPair,aPair->iReq,aPair->iTrans ));
623 CLIENT_PRINT(("DChannelIicClient::InsertPairs ... and aCbPair=0x%x, aCbPair->iCb=0x%x, aCbPair-iTrans=0x%x\n",aCbPair,aCbPair->iCb,aCbPair->iTrans ));
629 if((r = iTransStatArrayByTrans.InsertInOrder(aPair,TransStatusOrderByTrans)) == KErrNone)
631 if((r = iTransStatArrayByStatus.InsertInOrder(aPair,TransStatusOrderByStatus)) == KErrNone)
633 if((r = iTransCbArrayByTrans.InsertInOrder(aCbPair,TransCbOrderByTrans))!=KErrNone)
635 CLIENT_PRINT(("DChannelIicClient::InsertPairs, aCbPair=0x%x InsertInOrder(status) returned %d\n",aCbPair,r));
640 CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(status) returned %d\n",aPair,r));
645 CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(trans) returned %d\n",aPair,r));
652 //dummy call back func is provided for asyn call in priority test
653 static void DummyCallbackFunc(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt /*aResult*/, TAny* /*aParam*/)
658 static void AsyncCallbackFunc(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam)
660 (void)aBusId; // aBusId is not used if CLIENT_PRINT is disabled
661 CLIENT_PRINT(("> AsyncCallbackFunc() - aTrans=0x%x, aBusId=0x%x, aResult=%d, aParam=0x%x\n",aTrans,aBusId,aResult,aParam));
662 DChannelIicClient* channel = (DChannelIicClient*)aParam;
663 CLIENT_PRINT(("AsyncCallbackFunc() - channel=0x%x\n",channel));
665 // Use the channel to get the user-side client's TRequestStatus and complete it with aResult
666 TTransStatusPair* searchPair = new TTransStatusPair();
667 searchPair->iTrans = aTrans;
668 channel->GetWriteAccess();
670 TInt pairIndex = (channel->iTransStatArrayByTrans).FindInOrder(searchPair,TransStatusOrderByTrans);
674 CLIENT_PRINT(("AsyncCallbackFunc() - (trans) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
677 TTransStatusPair* pairPtr = (channel->iTransStatArrayByTrans)[pairIndex];
678 TRequestStatus* status = pairPtr->iReq;
680 // Now remove the TTransStatusPair objects in iTransStatArrayByTrans, iTransStatArrayByStatus
681 (channel->iTransStatArrayByTrans).Remove(pairIndex);
682 pairIndex = (channel->iTransStatArrayByStatus).FindInOrder(pairPtr,TransStatusOrderByStatus);
685 CLIENT_PRINT(("AsyncCallbackFunc() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndex,status));
688 (channel->iTransStatArrayByStatus).Remove(pairIndex);
690 // Now remove the TTransCbPair object in iTransCbArrayByTrans
691 TTransCbPair* SearchCbPair = new TTransCbPair();
692 SearchCbPair->iTrans = aTrans;
693 pairIndex = (channel->iTransCbArrayByTrans).FindInOrder(SearchCbPair,TransCbOrderByTrans);
697 CLIENT_PRINT(("AsyncCallbackFunc() - (cb) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
700 TTransCbPair* cbPair = (channel->iTransCbArrayByTrans)[pairIndex];
701 (channel->iTransCbArrayByTrans).Remove(pairIndex);
704 channel->FreeWriteAccess();
706 Kern::RequestComplete(channel->iClient, status, aResult);
707 // We should call CleanupExtractTrans() to delete all the objects created in ExtractTransData()
708 channel->CleanupExtractTrans(pairPtr->iTrans);
709 // The object referred to be pairPtr is finished with and can be deleted
710 channel->CleanupTransaction(pairPtr->iTrans);
715 void DDeviceIicClient::GetCaps(TDes8& aDes) const
716 // Return the IicClient capabilities.
718 CLIENT_PRINT(("> DDeviceIicClient::GetCaps(TDes8& aDes) const"));
719 TPckgBuf<TCapsIicClient> b;
720 b().version=TVersion(KIicClientMajorVersionNumber,
721 KIicClientMinorVersionNumber,
722 KIicClientBuildVersionNumber);
723 Kern::InfoCopy(aDes,b);
727 TInt DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)
728 // Create a channel on the device.
730 CLIENT_PRINT(("> DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)"));
731 if(iOpenChannels>=KMaxNumChannels)
733 aChannel=new DChannelIicClient;
734 return aChannel?KErrNone:KErrNoMemory;
737 #ifdef STANDALONE_CHANNEL
739 TInt GetChanPtr(const TInt aBusId, TInt &aIndex, DIicClientChan*& aChan)
741 __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
743 chanId = GET_CHAN_NUM(aBusId);
744 __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, chanId=0x%x\n",chanId));
745 DIicClientChan chanEntry(NULL,(TInt8)chanId, DIicBusChannel::EMasterSlave);
746 TInt r = KErrNotFound;
747 aIndex = ChannelArray.FindInOrder(&chanEntry, EntryOrder);
750 aChan = ChannelArray[aIndex];
754 __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, chanPtr=0x%x, index=%d\n",aChan,aIndex));
759 DECLARE_STANDARD_LDD()
761 //If in STANDALONE_CHANNEL mode, the client creates a list of channels
762 #ifdef STANDALONE_CHANNEL
763 DIicClientChan* aClientChan;
765 DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
767 for(i=0; i<NUM_CHANNELS_SPI; i++)
769 CLIENT_PRINT(("\n"));
770 #if defined(MASTER_MODE)
771 if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::EMaster))
773 chan=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
776 CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
779 CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
780 if(((DSimulatedIicBusChannelMasterSpi*)chan)->Create()!=KErrNone)
785 aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMaster);
791 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
800 #if defined(MASTER_MODE) && defined(SLAVE_MODE)
801 if(CHANNEL_TYPE_SPI(i) == DIicBusChannel::EMasterSlave)
803 //For MasterSlave channel, the client creates a Master channel, a Slave
804 //channel and a MasterSlave Channel, then store all of them in ChannelArray.
805 chanM=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
809 chanS=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
815 chan=new DIicBusChannelMasterSlave(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i),(DSimulatedIicBusChannelMasterSpi*)chanM,(DSimulatedIicBusChannelSlaveSpi*)chanS); // Generic implementation
818 CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
823 CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
824 if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
831 aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMasterSlave);
839 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
850 #if defined(SLAVE_MODE)
851 if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::ESlave))
853 chan=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
856 CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
859 CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
860 if(((DSimulatedIicBusChannelSlaveSpi*)chan)->Create()!=KErrNone)
865 aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::ESlave);
871 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
880 #if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
881 #error I2C mode not defined as Master, Slave nor Master-Slave
885 for(i=0; i<NUM_CHANNELS_I2C; i++)
887 CLIENT_PRINT(("\n"));
888 #if defined(MASTER_MODE)
889 if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::EMaster))
891 chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
894 CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
897 CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
898 if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
903 aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
909 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
918 #if defined(MASTER_MODE) && defined(SLAVE_MODE)
919 if(CHANNEL_TYPE_I2C(i) == DIicBusChannel::EMasterSlave)
921 chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
925 chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
931 //The client doesn't create the Master and Slave channels, as they should be created
932 //in MasterSlave channel's DoCreate().
933 chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
936 CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
941 CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
942 if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
949 aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
957 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
968 #if defined(SLAVE_MODE)
969 if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::ESlave))
971 chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
974 CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
977 CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
978 if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
983 aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
989 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
998 #if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
999 #error I2C mode not defined as Master, Slave nor Master-Slave
1004 return new DDeviceIicClient;
1009 DChannelIicClient::DChannelIicClient()
1012 CLIENT_PRINT(("> DChannelIicClient::DChannelIicClient()"));
1013 iClient=&Kern::CurrentThread();
1014 // Increase the DThread's ref count so that it does not close without us
1018 DChannelIicClient::~DChannelIicClient()
1021 CLIENT_PRINT(("> DChannelIicClient::~DChannelIicClient()"));
1022 __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelIicClient::~DChannelIicClient()"));
1024 iArrayMutex->Close(NULL);
1025 iChanArrWrtSem->Close(NULL);
1027 // decrement the DThread's reference count
1028 Kern::SafeClose((DObject*&)iClient, NULL);
1030 iTransStatArrayByTrans.Reset();
1031 iTransStatArrayByStatus.Reset();
1032 iTransCbArrayByTrans.Reset();
1033 iExtractInfoArray.Reset();
1037 TInt DChannelIicClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1039 CLIENT_PRINT(("> DChannelIicClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
1040 TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicClientThreadPriority,KIicClientThreadName);
1046 r = InitIicClient();
1050 void DChannelIicClient::HandleMsg(TMessageBase* aMsg)
1052 TThreadMessage& m=*(TThreadMessage*)aMsg;
1055 CLIENT_PRINT((" >ldd: DChannelIicClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
1057 if (id == (TInt)ECloseMsg)
1059 iMsgQ.iMessage->Complete(KErrNone,EFalse);
1062 else if (id == KMaxTInt)
1065 m.Complete(KErrNone,ETrue);
1071 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1072 TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
1075 Kern::RequestComplete(iClient, pS, r);
1077 m.Complete(KErrNone,ETrue);
1081 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
1082 m.Complete(r,ETrue);
1086 TInt DChannelIicClient::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback/*NULL*/)
1089 #ifndef STANDALONE_CHANNEL
1091 r = IicBus::QueueTransaction(aBusId, aTransaction);
1093 r = IicBus::QueueTransaction(aBusId, aTransaction, aCallback);
1095 __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1098 return KErrArgument;
1101 // Get a pointer to the channel
1103 DIicClientChan* chanPtr = NULL;
1104 r = GetChanPtr(aBusId, dumInt, chanPtr);
1113 switch(chanPtr->GetChanType())
1115 // QueueTransaction requests are only supported by channels in Master mode.
1116 case DIicBusChannel::ESlave:
1118 r = KErrNotSupported;
1121 // If the request is supported by the Master channel, send it to the channel for processing in its thread
1122 case DIicBusChannel::EMasterSlave:
1125 aTransaction->iBusId = aBusId;
1127 r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
1129 r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
1132 case DIicBusChannel::EMaster:
1134 aTransaction->iBusId = aBusId;
1136 r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
1138 r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
1152 TInt DChannelIicClient::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1155 #ifndef STANDALONE_CHANNEL
1156 r = IicBus::CancelTransaction(aBusId, aTransaction);
1158 __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1161 return KErrArgument;
1166 DIicClientChan* chanPtr = NULL;
1169 r = GetChanPtr(aBusId, dumInt, chanPtr);
1178 // QueueTransaction requests are only supported by channels in Master mode.
1179 switch(chanPtr->GetChanType())
1181 case DIicBusChannel::ESlave:
1183 r = KErrNotSupported;
1186 case DIicBusChannel::EMasterSlave:
1188 r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
1191 case DIicBusChannel::EMaster:
1193 r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
1209 TInt DChannelIicClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
1212 #ifndef STANDALONE_CHANNEL
1213 r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
1217 DIicClientChan* chanPtr = NULL;
1220 r = GetChanPtr(aId, dumInt, chanPtr);
1229 r = (chanPtr->GetChannelPtr())->StaticExtension(aFunction, aParam1, aParam2);
1237 TInt DChannelIicClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
1240 #ifndef STANDALONE_CHANNEL
1241 r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
1243 // Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
1244 if(!aCallback || !aConfigHdr)
1246 return KErrArgument;
1251 DIicClientChan* chanPtr = NULL;
1254 r = GetChanPtr(aBusId, chanIndex, chanPtr);
1263 switch(chanPtr->GetChanType())
1265 // CaptureChannel requests are only supported by channels in Slave mode.
1266 case DIicBusChannel::EMaster:
1268 r = KErrNotSupported;
1271 case DIicBusChannel::EMasterSlave:
1273 r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
1276 case DIicBusChannel::ESlave:
1278 r = ((DIicBusChannelSlave*)(chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
1286 // For synchronous capture, if successful then install the channel
1291 iCapturedChannel.iChanPtr = chanPtr;
1292 iCapturedChannel.iChannelId = iChannelId;
1295 //For asynchronous capture, record chanPtr, if later failed capture,
1296 //clean iCapturedChannel in client's callback.
1297 iCapturedChannel.iChanPtr = chanPtr;
1306 TInt DChannelIicClient::ReleaseChannel(TInt aChannelId)
1309 #ifndef STANDALONE_CHANNEL
1310 r = IicBus::ReleaseChannel(aChannelId);
1312 __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
1313 if(iCapturedChannel.iChannelId != aChannelId)
1314 return KErrNotFound;
1316 if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::EMasterSlave)
1317 r = ((DIicBusChannelMasterSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
1318 else if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::ESlave)
1319 r = ((DIicBusChannelSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
1320 //After release channel, reset iCapturedChan
1321 iCapturedChannel.iChanPtr = NULL;
1322 iCapturedChannel.iChannelId = 0;
1327 void DChannelIicClient::DoCancel(TInt aMask)
1329 // Cancel an outstanding request.
1330 CLIENT_PRINT(("DChannelIicClient::DoCancel invoked with aMask=0x%x\n", aMask));
1332 // inline void CancelAsyncOperation(TRequestStatus* aStatus, TInt aBusId) {TInt* parms[2]; parms[0]=(TInt*)aStatus; parms[1]=(TInt*)aBusId;DoCancel((TInt)&parms[0]);}
1333 // aMask has the address on TInt* parms[2]
1334 // parms[0] = TRequestStatus pointer
1335 // parms[1] = Bus Identifier
1337 TInt r=Kern::ThreadRawRead(iClient,(TAny*)aMask,&(parms[0]),2*sizeof(TInt*));
1340 CLIENT_PRINT(("DChannelIicClient::DoCancel ERROR - Can't read parms[]\n"));
1341 return; // Can't proceed if can't access request parameters
1343 CLIENT_PRINT(("DChannelIicClient::DoCancel - TRequestStatus 0x%x, BusID = 0x%x\n",parms[0],parms[1]));
1345 TTransStatusPair* searchPair = new TTransStatusPair();
1346 TTransCbPair* cbPair = new TTransCbPair();
1347 searchPair->iReq = (TRequestStatus*)(parms[0]);
1352 TInt pairIndexByStatus = iTransStatArrayByStatus.FindInOrder(searchPair,TransStatusOrderByStatus);
1353 CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByStatus=0x%x\n",pairIndexByStatus));
1354 TInt pairIndexByTrans = KErrNotFound;
1356 if(pairIndexByStatus<0)
1358 // If the TRequestStatus object is not found then either the value was invalid or
1359 // the object may already have been completed.
1362 CLIENT_PRINT(("DChannelIicClient::DoCancel() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndexByStatus,parms[0]));
1366 // The status-transaction pair exists in the status-index array - so remove it
1367 TTransStatusPair* pairPtrStatus = iTransStatArrayByStatus[pairIndexByStatus];
1368 iTransStatArrayByStatus.Remove(pairIndexByStatus);
1370 pairIndexByTrans = iTransStatArrayByTrans.FindInOrder(pairPtrStatus,TransStatusOrderByTrans);
1371 CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByTrans=0x%x\n",pairIndexByTrans));
1372 if(pairIndexByTrans>=0)
1374 iTransStatArrayByTrans.Remove(pairIndexByTrans);
1379 CLIENT_PRINT(("DChannelIicClient::DoCancel pairPtrStatus=0x%x\n", pairPtrStatus));
1381 // Allow the bus to perform any required processing
1382 TIicBusTransaction* trans = pairPtrStatus->iTrans;
1383 CLIENT_PRINT(("DChannelIicClient::CancelTransaction - invoking with busId=0x%x, trans=0x%x\n",(TInt)(parms[1]),trans));
1384 r = CancelTransaction((TInt)(parms[1]), trans);
1385 cbPair->iTrans=trans;
1386 TInt cbIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
1387 TTransCbPair* theCbPair = iTransCbArrayByTrans[cbIndex];
1388 TIicBusCallback* cb= (iTransCbArrayByTrans[cbIndex])->iCb;
1389 iTransCbArrayByTrans.Remove(cbIndex);
1391 // Complete the TRequestStatus object according to the returned value
1392 TRequestStatus* status= (TRequestStatus*)(parms[0]);
1393 Kern::RequestComplete(iClient, status, r);
1398 // We should call CleanupExtractTrans() to delete all the objects we created in ExtractTransData()
1399 CleanupExtractTrans(trans);
1400 CleanupTransaction(trans);
1401 delete pairPtrStatus;
1411 // Function to support preamble testing
1412 void PreambleCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
1414 CLIENT_PRINT(("IIC Client: PreambleCallbackFunc invoked\n"));
1415 // aParam is the address of the client that created the transaction object
1416 __ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("PreambleCallbackFunc, client address ==NULL",__LINE__));
1417 DChannelIicClient *client = (DChannelIicClient*)aParam;
1418 __ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("PreambleCallbackFunc, iClient==NULL",__LINE__));
1419 __ASSERT_ALWAYS(client->iPreambleStatus!=NULL,Kern::Fault("PreambleCallbackFunc, iPreambleStatus==NULL",__LINE__));
1420 Kern::RequestComplete(client->iClient, client->iPreambleStatus, KErrNone);
1423 TIicBusTransaction* DChannelIicClient::iMultiTransac;
1425 // Function to support multi transc testing
1426 TIicBusTransaction* DChannelIicClient::MultiTranscCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
1428 CLIENT_PRINT(("IIC Client: MultiTranscCallbackFunc invoked\n"));
1429 // aParam is the address of the client that created the transaction object
1430 __ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("MultiTranscCallbackFunc, client address ==NULL",__LINE__));
1431 DChannelIicClient *client = (DChannelIicClient*)aParam;
1432 __ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("MultiTranscCallbackFunc, iClient==NULL",__LINE__));
1433 __ASSERT_ALWAYS(client->iMultiTranscStatus!=NULL,Kern::Fault("MultiTranscCallbackFunc, iMultiTranscStatus==NULL",__LINE__));
1434 Kern::RequestComplete(client->iClient, client->iMultiTranscStatus, KErrNone);
1435 return iMultiTransac;
1438 TInt DChannelIicClient::CleanupExtractTrans(TIicBusTransaction* aTrans)
1440 // Clean up the data created in ExtractTransData()
1441 TExtractInfo *extractInfo = new TExtractInfo();
1442 extractInfo->iTrans = aTrans;
1443 TInt index = iExtractInfoArray.FindInOrder(extractInfo, ExtractInfoOrderByTrans);
1446 delete iExtractInfoArray[index];
1447 iExtractInfoArray.Remove(index);
1453 TInt DChannelIicClient::ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans)
1455 // Utility function to create a TIicBusTransaction object from the parameters passed by the user-side TUsideTracnDesc object
1458 TUsideTracnDesc usTrans;
1459 r=Kern::ThreadRawRead(iClient,aUsideTrancnDesc,&usTrans,sizeof(TUsideTracnDesc));
1462 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans\n"));
1463 return KErrGeneral; // Can't proceed if can't access request parameters
1465 // Ensure pointers potentially used for allocation are NULL, to facilitate cleanup
1469 iTransPreamble=NULL;
1472 // Get the header (depends on the bus type)
1473 TBusType busType = usTrans.iType;
1474 TConfigSpiBufV01 *spiBuf = NULL;
1475 TConfigI2cBufV01 *i2cBuf = NULL;
1476 // extractInfo is used to keep the bufPtr and tfer of the transaction,
1477 // and will later be stored in iExtractInfoArray, sorting by transaction.
1478 // The extractInfo object will be freed in CleanupExtractTrans.
1479 TExtractInfo *extractInfo = new TExtractInfo();
1483 if((spiBuf = new TConfigSpiBufV01()) == NULL)
1485 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate spiBuf\n"));
1486 return KErrNoMemory;
1488 if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
1490 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to spiBuf\n"));
1493 bufPtr=(TDes8*)spiBuf;
1495 else if(busType == EI2c)
1497 if((i2cBuf = new TConfigI2cBufV01()) == NULL)
1499 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate i2cBuf\n"));
1500 return KErrNoMemory;
1502 if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *i2cBuf, 0, KChunkShiftBy0 ))!=KErrNone)
1504 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to i2cBuf\n"));
1507 bufPtr=(TDes8*)i2cBuf;
1511 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unrecognised bus type\n"));
1514 extractInfo->iBufPtr = bufPtr;
1515 // Get the half-duplex transfer information
1516 TUsideTferDesc* usTferPtr = usTrans.iHalfDuplexTrans;
1517 TUsideTferDesc usTfer;
1518 r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
1521 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex usTfer\n"));
1522 return KErrGeneral; // Can't proceed if can't access request parameters
1524 // Need to access the descriptor holding the information to be transferred
1525 TBuf8 <MAX_TRANS_LENGTH> tferData;
1526 r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,tferData,0,KChunkShiftBy0);
1529 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex tferData\n"));
1530 return KErrGeneral; // Can't proceed if can't access request parameters
1533 TIicBusTransfer::TReqType type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
1534 tfer7 = new TIicBusTransfer(type, usTfer.iBufGranularity, &tferData);
1535 extractInfo->iTfer = tfer7;
1536 // Construct the appropriate transaction object with the half-duplex information
1537 TUint8 transFlags = usTrans.iFlags;
1539 if((transFlags&KTransactionWithPreamble)&&(transFlags&KTransactionWithMultiTransc))
1541 if(usTrans.iPreambleArg == NULL)
1543 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
1544 return KErrArgument;
1546 if(usTrans.iMultiTranscArg == NULL)
1548 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
1549 return KErrArgument;
1551 iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
1552 iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
1553 TIicBusTransactionPreambleExt* transExt;
1555 transExt = new TIicBusTransactionPreambleExt(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this,
1556 (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
1557 if(transExt == NULL)
1559 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1560 return KErrNoMemory; // Can't proceed if can't access request parameters
1565 else if(transFlags & KTransactionWithPreamble)
1567 // Preamble required - construct the derived-class transaction object
1568 if(usTrans.iPreambleArg == NULL)
1570 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - preamble TRequestStatus==NULL\n"));
1571 return KErrArgument;
1573 iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
1574 TIicBusTransactionPreamble* TransPreamble;
1575 TransPreamble = new TIicBusTransactionPreamble(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this);
1576 if(TransPreamble == NULL)
1578 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1579 return KErrNoMemory; // Can't proceed if can't access request parameters
1581 aTrans = TransPreamble;
1583 else if(transFlags & KTransactionWithMultiTransc)
1585 // Preamble required - construct the derived-class transaction object
1586 if(usTrans.iMultiTranscArg == NULL)
1588 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Multi Transc TRequestStatus==NULL\n"));
1589 return KErrArgument;
1591 iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
1592 TIicBusTransactionMultiTransc* transMultiTransc;
1593 transMultiTransc = new TIicBusTransactionMultiTransc(bufPtr, tfer7, (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
1594 if(transMultiTransc == NULL)
1596 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1597 return KErrNoMemory; // Can't proceed if can't access request parameters
1599 aTrans = transMultiTransc;
1603 // Preamble not required
1604 aTrans = new TIicBusTransaction(bufPtr, tfer7);
1607 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1608 return KErrNoMemory; // Can't proceed if can't access request parameters
1612 // If full duplex transaction is required get that information, too
1613 usTferPtr = usTrans.iFullDuplexTrans;
1616 r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
1619 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex usTfer\n"));
1620 return KErrGeneral; // Can't proceed if can't access request parameters
1622 // Need to access the descriptor holding the information to be transferred
1623 TBuf8 <MAX_TRANS_LENGTH> fdTferData;
1624 r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,fdTferData,0,KChunkShiftBy0);
1627 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex tferData\n"));
1628 return KErrGeneral; // Can't proceed if can't access request parameters
1631 type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
1632 r=aTrans->SetFullDuplexTrans(iFdTfer);
1635 CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - SetFullDuplexTrans returned %d\n",r));
1639 extractInfo->iTrans = aTrans;
1640 iExtractInfoArray.InsertInOrder(extractInfo, ExtractInfoOrderByTrans);
1644 #define KMaxTferTextLength 20
1645 #define KLongNodeTestLength 15
1646 #define KShortNodeTestLength 5
1647 _LIT(KFullTracnHdrText,"Full duplex test"); // length = 22
1648 #define KFullTracnHdrTextLength 16
1651 // Create transfer list with three nodes
1652 // All memories are allocated from the kernel heap and referenced by class members
1653 // DeleteFullDuplexTest should be called to release memory after use.
1654 // List created here will be assigned to iHalfDuplexTrans in TIicBusTransaction
1655 // If aNodeLength3 = 0, only return a 2 nodes transfer
1656 TInt DChannelIicClient::CreateTransferListHalfDuplex(
1657 TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1658 TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1659 TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
1661 buf1 = HBuf8::New(KMaxTferTextLength);
1662 buf2 = HBuf8::New(KMaxTferTextLength);
1663 buf3 = HBuf8::New(KMaxTferTextLength);
1664 tfer1 = new TIicBusTransfer(aNodeDir1,8,buf1);
1665 tfer2 = new TIicBusTransfer(aNodeDir2,8,buf2);
1666 tfer3 = new TIicBusTransfer(aNodeDir3,8,buf3);
1668 if(buf1 == NULL||buf2 == NULL||buf3 == NULL||
1669 tfer1 == NULL||tfer2 == NULL||tfer3 == NULL)
1671 delete buf1; delete buf2; delete buf3;
1672 delete tfer1; delete tfer2; delete tfer3;
1673 return KErrNoMemory;
1677 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf1->Append('*');
1678 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf2->Append('*');
1679 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf3->Append('*');
1681 tfer1->LinkAfter(tfer2);
1686 tfer2->LinkAfter(tfer3);
1693 // Create transfer list with three nodes
1694 // All memories are allocated from the kernel heap and referenced by class members
1695 // DeleteFullDuplexTest should be called to release memory after use.
1696 // List created here will be assigned to iFullDuplexTrans in TIicBusTransaction
1697 // If aNodeLength3 = 0, only return a 2 nodes transfer
1698 TInt DChannelIicClient::CreateTransferListFullDuplex(
1699 TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1700 TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1701 TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
1703 buf4 = HBuf8::New(KMaxTferTextLength);
1704 buf5 = HBuf8::New(KMaxTferTextLength);
1705 buf6 = HBuf8::New(KMaxTferTextLength);
1706 tfer4 = new TIicBusTransfer(aNodeDir1,8,buf4);
1707 tfer5 = new TIicBusTransfer(aNodeDir2,8,buf5);
1708 tfer6 = new TIicBusTransfer(aNodeDir3,8,buf6);
1710 if(buf4 == NULL||buf5 == NULL||buf6 == NULL||
1711 tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
1713 delete buf4; delete buf5; delete buf6;
1714 delete tfer4; delete tfer5; delete tfer6;
1715 return KErrNoMemory;
1719 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf4->Append('*');
1720 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf5->Append('*');
1721 for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf6->Append('*');
1723 tfer4->LinkAfter(tfer5);
1728 tfer5->LinkAfter(tfer6);
1735 // Delete transaction and all allocated transfers and buffers
1736 TInt DChannelIicClient::DeleteFullDuplexTest(TIicBusTransaction *aTrans)
1738 delete buf1; delete buf2; delete buf3;
1739 delete tfer1; delete tfer2; delete tfer3;
1741 delete buf4; delete buf5; delete buf6;
1742 delete tfer4; delete tfer5; delete tfer6;
1750 // Do full duplex creation test
1751 TInt DChannelIicClient::DoCreateFullDuplexTransTest(TInt aTestType)
1753 CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest starts\n"));
1758 case RBusDevIicClient::ETestValidFullDuplexTrans:
1760 // equal length, opposite transfer direction
1761 r = CreateTransferListHalfDuplex(
1762 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1763 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1764 TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1765 if(r!=KErrNone) break;
1766 r = CreateTransferListFullDuplex(
1767 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1768 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1769 TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1770 if(r!=KErrNone) break;
1773 case RBusDevIicClient::ETestInvalidFullDuplexTrans1:
1775 // equal length, same transfer direction
1776 r = CreateTransferListHalfDuplex(
1777 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1778 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1779 TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1780 if(r!=KErrNone) break;
1781 r = CreateTransferListFullDuplex(
1782 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1783 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1784 TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1785 if(r!=KErrNone) break;
1788 case RBusDevIicClient::ETestInvalidFullDuplexTrans2:
1790 // different, opposite transfer direction
1791 r = CreateTransferListHalfDuplex(
1792 TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
1793 TIicBusTransfer::EMasterRead, KShortNodeTestLength,
1794 TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1795 if(r!=KErrNone) break;
1796 r = CreateTransferListFullDuplex(
1797 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1798 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1799 TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1800 if(r!=KErrNone) break;
1803 case RBusDevIicClient::ETestLastNodeFullDuplexTrans:
1805 // different length for the last node
1806 r = CreateTransferListHalfDuplex(
1807 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1808 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1809 TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1810 if(r!=KErrNone) break;
1811 r = CreateTransferListFullDuplex(
1812 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1813 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1814 TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1815 if(r!=KErrNone) break;
1818 case RBusDevIicClient::ETestDiffNodeNoFullDuplexTrans:
1820 // equal length, opposite transfer direction
1821 r = CreateTransferListHalfDuplex(
1822 TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1823 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1824 TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1825 if(r!=KErrNone) break;
1826 r = CreateTransferListFullDuplex(
1827 TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1828 TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
1829 TIicBusTransfer::EMasterRead, 0);
1830 if(r!=KErrNone) break;
1839 header = HBuf8::New(KFullTracnHdrTextLength);
1840 TIicBusTransaction *Trans = new TIicBusTransaction(header,tfer1);
1842 if((r!=KErrNone) || (header == NULL) || (Trans == NULL))
1844 CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest ERROR - failed to allocate the necessary memory\n"));
1845 DeleteFullDuplexTest(Trans);
1846 return KErrNoMemory;
1849 header->Copy(KFullTracnHdrText);
1851 TInt TestResult = Trans->SetFullDuplexTrans(tfer4);
1853 CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest IIC after SetFullDuplexTrans TestResult =%d\n", TestResult));
1855 r = DeleteFullDuplexTest(Trans);
1862 TInt DChannelIicClient::CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf)
1863 // Utility function to create a buffer for the SPI bus
1865 TInt r=CreateSpiBuf(aBuf, ESpiWordWidth_8, 100000, ESpiPolarityLowRisingEdge, 100 ,ELittleEndian, EMsbFirst, 10, ESpiCSPinActiveLow);
1869 // DoPriorityTest does the following actions:
1870 // 1. switch the bus (only use SPI test PSL) to priority test mode
1871 // 2. create 5 test transactions with different priorities and 1 blocking transaction
1872 // 3. enable blocking in test channel
1873 // we can only block the test channel, we cannot suspend the bus controller
1874 // 3. send blocking transaction to the test channel
1875 // the blocking transaction is just normal transaction.
1876 // the test channel will be blocked once the first transaction is arrived
1877 // 4. send test transactions in opposite order to their priority
1878 // 5. unblock test channel
1879 // 6. read test result from channel
1880 // 7. switch the bus to normal mode
1881 TInt DChannelIicClient::DoPriorityTest(TInt aBusId)
1883 TInt TestResult=KErrNone;
1884 // Use the IIC StaticExtension interface to pass the request to the bus implementation
1885 // To support testing, any values of aId for StaticExtension must be shifted left one place
1886 TUint testId = ((TUint)(RBusDevIicClient::ECtlIoPriorityTest))<<1;
1889 r = StaticExtension(aBusId, testId, NULL, NULL);
1890 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1893 buf1 = HBuf8::New(1);
1894 buf2 = HBuf8::New(1);
1895 buf3 = HBuf8::New(1);
1896 buf4 = HBuf8::New(1);
1897 buf5 = HBuf8::New(1);
1898 //buffer for blocking transaction
1899 buf6 = HBuf8::New(1);
1901 if(buf1 == NULL||buf2 == NULL||buf3 == NULL||buf4 == NULL||buf5 == NULL||buf6 == NULL)
1903 delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1904 r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1905 return KErrNoMemory;
1907 tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
1908 tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf2);
1909 tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
1910 tfer4 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf4);
1911 tfer5 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf5);
1912 //transfer for blocking transaction
1913 tfer6 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf6);
1915 if(tfer1 == NULL||tfer2 == NULL||tfer3 == NULL||tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
1917 delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1918 delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1919 r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1920 return KErrNoMemory;
1923 TConfigSpiBufV01* spiHeader1 = NULL;
1924 TConfigSpiBufV01* spiHeader2 = NULL;
1925 TConfigSpiBufV01* spiHeader3 = NULL;
1926 TConfigSpiBufV01* spiHeader4 = NULL;
1927 TConfigSpiBufV01* spiHeader5 = NULL;
1928 TConfigSpiBufV01* spiHeaderBlock = NULL; //header for blocking transaction
1931 TInt r = CreateDefaultSpiBuf(spiHeader1);
1932 if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader2);
1933 if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader3);
1934 if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader4);
1935 if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader5);
1936 //header for blocking transaction
1937 if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeaderBlock);
1939 if(r != KErrNone||spiHeader1 == NULL||spiHeader2 == NULL||spiHeader3 == NULL||spiHeader4 == NULL||spiHeader5 == NULL||spiHeaderBlock == NULL)
1941 delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1942 delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1943 delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
1944 r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1945 return KErrNoMemory;
1948 TIicBusTransaction* Transc1; Transc1 = new TIicBusTransaction(spiHeader1,tfer1, KPriorityTestPrio[0]);
1949 TIicBusTransaction* Transc2; Transc2 = new TIicBusTransaction(spiHeader2,tfer2, KPriorityTestPrio[1]);
1950 TIicBusTransaction* Transc3; Transc3 = new TIicBusTransaction(spiHeader3,tfer3, KPriorityTestPrio[2]);
1951 TIicBusTransaction* Transc4; Transc4 = new TIicBusTransaction(spiHeader4,tfer4, KPriorityTestPrio[3]);
1952 TIicBusTransaction* Transc5; Transc5 = new TIicBusTransaction(spiHeader5,tfer5, KPriorityTestPrio[4]);
1953 //blocking transaction
1954 TIicBusTransaction* TranscBlock; TranscBlock = new TIicBusTransaction(spiHeaderBlock,tfer6, KPriorityTestPrio[5]);
1956 if(Transc1 == NULL||Transc2 == NULL||Transc3 == NULL||Transc4 == NULL||Transc5 == NULL||TranscBlock == NULL)
1958 delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1959 delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1960 delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
1961 delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
1962 r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1963 return KErrNoMemory;
1966 //dummy call back func is provided for asyn call
1967 TIicBusCallback* cb = new TIicBusCallback(DummyCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
1969 // block the device channel. the channel will not be blocked until the first transaction arrive the channel
1970 // To support testing, any values of aId for StaticExtension must be shifted left one place
1971 TUint testId=((TUint)RBusDevIicClient::ECtlIoBlockReqCompletion)<<1;
1972 r = StaticExtension(aBusId, testId, NULL, NULL);
1973 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1975 r = QueueTransaction(aBusId, TranscBlock, cb); //send TranscBlock to block the channel
1976 // send ordered transactions
1977 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1979 r = QueueTransaction(aBusId, Transc1, cb);
1980 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1981 r = QueueTransaction(aBusId, Transc2, cb);
1982 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1983 r = QueueTransaction(aBusId, Transc3, cb);
1984 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1985 r = QueueTransaction(aBusId, Transc4, cb);
1986 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1987 r = QueueTransaction(aBusId, Transc5, cb);
1988 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1990 // unblock device channel
1991 testId=((TUint)RBusDevIicClient::ECtlIoUnblockReqCompletion)<<1;
1992 r = StaticExtension(aBusId, testId, NULL, NULL);
1993 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1995 #define KPriorityTestGetResultRetry 3
1996 for(TInt i=0; i<KPriorityTestGetResultRetry ; i++)
1999 testId=((TUint)RBusDevIicClient::EGetTestResult)<<1;
2000 TestResult = StaticExtension(aBusId, testId, NULL, NULL);
2001 if(TestResult!=KErrNotReady) break;
2006 delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
2007 delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
2008 delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
2009 delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
2012 r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
2016 TInt DChannelIicClient::ConstructTransactionOne(TIicBusTransaction*& aTrans)
2018 // Transaction is to contain three transfers, with data defined by
2019 // KTransOneTferOne[], KTransOneTferTwo[], KTransOneTferThree[]
2020 buf1 = HBuf8::New(21);
2021 buf2 = HBuf8::New(8);
2022 buf3 = HBuf8::New(6);
2023 tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
2024 tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterRead,8,buf2);
2025 tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
2026 TInt r = CreateDefaultSpiBuf(spiHeader);
2027 if((r != KErrNone)||(spiHeader == NULL)||(buf1 == NULL)||(buf2 == NULL)||(buf3 == NULL)||(tfer1 == NULL)||(tfer2 == NULL)||(tfer3 == NULL))
2029 CLIENT_PRINT(("DChannelIicClient::ConstructTransactionOne ERROR - failed to allocate the necessary memory\n"));
2038 return KErrNoMemory;
2040 aTrans = new TIicBusTransaction(spiHeader,tfer1);
2041 buf1->Copy(&(KTransOneTferOne[0]),21);
2042 buf2->Copy(&(KTransOneTferTwo[0]),8);
2043 buf3->Copy(&(KTransOneTferThree[0]),6);
2044 tfer1->LinkAfter(tfer2);
2045 tfer2->LinkAfter(tfer3);
2049 void DChannelIicClient::CleanupTransactionOne(TIicBusTransaction*& aTrans)
2051 // Release the allocated memory
2071 void DChannelIicClient::CleanupTransaction(TIicBusTransaction*& aTrans)
2077 TIicBusTransfer* currTfer = iTfer;
2078 TIicBusTransfer* nextTfer = NULL;
2081 TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
2084 currTfer = nextTfer;
2093 TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
2096 currTfer = nextTfer;
2106 if(iTransPreamble!=NULL)
2108 delete iTransPreamble;
2109 iTransPreamble=NULL;
2113 void DChannelIicClient::TransModifCallback(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt aResult, TAny* aParam)
2115 // Callback function used to test re-use of transaction and transfer buffers
2116 // aParam is the address of the simulated client driver
2117 DChannelIicClient* channel = (DChannelIicClient*)aParam;
2118 TTransBufReuseData* reuseData = &(channel->iTransBufReuseData);
2120 // Since the transaction is no longer queued, should be able to modify the transfer and transaction content
2121 channel->TestTransModification(reuseData->iTransaction, reuseData->iHdTfer, reuseData->iFdTfer, reuseData->iHdr);
2123 // Complete the user's request, delete objects allocated for this test and return
2124 Kern::RequestComplete(channel->iClient, channel->iStatus, aResult);
2125 delete reuseData->iCallback; // Must do this before deleting the Transaction, in CleanupTransaction
2126 channel->CleanupTransaction(channel->iTrans);
2131 void DChannelIicClient::TestTransModification(TIicBusTransaction* aTransaction,
2132 TIicBusTransfer* aHdTfer,
2133 TIicBusTransfer* aFdTfer,
2136 // Function to test that the content of Transaction and Transfer objects can be modified
2137 // This assumes that the Transaction is in the appropriate state (EFree) - otherwise, the code will assert
2138 // This function also assumes that transaction has aleady added the half-duplex and full-duplex transfers
2139 // that are passed in as arguments, and that the transfers lists are non-NULL
2140 // The original type of the transfers (read, write) are ignored, since it is not of interest in this test -
2141 // instead, what is important is to ensure that the half-duplex and full-duplex transfer types are in opposing
2142 // directions - so the types are explicitly set in this test.
2144 TDes8* origBuf = NULL;
2145 TInt8 origGranularity = 0;
2147 // Create a buffer for use in this function
2148 _LIT(temporaryText,"Temporary Text");
2149 TBuf8<15> tempBuf_8;
2150 tempBuf_8.Copy(temporaryText);
2152 // Test modification of the two transfer lists while still part of the transaction
2153 origBuf = (TDes8*)(aHdTfer->GetBuffer());
2154 origGranularity = aHdTfer->WordWidth();
2155 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
2156 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
2158 origBuf = (TDes8*)(aFdTfer->GetBuffer());
2159 origGranularity = aFdTfer->WordWidth();
2160 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
2161 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
2163 // Test transfers can be removed from the transaction
2164 aTransaction->RemoveHalfDuplexTrans();
2165 aTransaction->RemoveFullDuplexTrans();
2167 // Test modification of the two transfer lists while not part of a transaction
2168 origBuf = (TDes8*)(aHdTfer->GetBuffer());
2169 origGranularity = aHdTfer->WordWidth();
2170 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
2171 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
2173 origBuf = (TDes8*)(aFdTfer->GetBuffer());
2174 origGranularity = aFdTfer->WordWidth();
2175 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
2176 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
2178 // Test transfers can be re-added to the transaction
2179 aTransaction->SetHalfDuplexTrans(aHdr,aHdTfer);
2180 aTransaction->SetFullDuplexTrans(aFdTfer);
2182 // Test modification of the two transfer lists now re-added to the transaction
2183 origBuf = (TDes8*)(aHdTfer->GetBuffer());
2184 origGranularity = aHdTfer->WordWidth();
2185 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
2186 aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
2188 origBuf = (TDes8*)(aFdTfer->GetBuffer());
2189 origGranularity = aFdTfer->WordWidth();
2190 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
2191 aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
2196 TInt DChannelIicClient::DoControl(TInt aId, TAny* a1, TAny* a2)
2198 CLIENT_PRINT(("DChannelIicClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
2200 // To support testing, any values of aId for StaticExtension must be shifted left one place
2201 // and for a Slave tests, the two msbs must be zero
2203 if((aId & KTestMasterControlIo) == KTestMasterControlIo)
2204 ctrlIoVal = (aId << 1);
2205 if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
2206 ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
2209 case(RBusDevIicClient::EQTransSync):
2211 // a1 specifies Bus Realisation Config to use
2212 // a2 is a pointer to TUsideTracnDesc
2213 TIicBusTransaction* trans = NULL;
2214 TIicBusTransfer* tfer = NULL;
2215 TConfigSpiBufV01 *spiBuf = NULL;
2217 //Read the transaction header to determin if it is a multi-transaction type
2218 TUsideTracnDesc usTrans;
2220 if((Kern::ThreadRawRead(iClient,a2,&usTrans,sizeof(TUsideTracnDesc)))!=KErrNone)
2222 CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
2226 if((usTrans.iFlags)&KTransactionWithMultiTransc)
2228 // Since we are testing a multi-transaction, create another transaction object iMultiTransac,
2229 // to represent the delayed part of the multi-transaction. After the preliminary
2230 // transaction(passed from t_iic, with one read transfer) has been performed,
2231 // the IIC code will find that it is part of a
2232 // multi-transaction; it will call the callback for the transaction(set as MultiTranscCallbackFunc,
2233 // in ExtractTransData) and this will return a pointer to the next part of the multi-transaction
2234 // to be performed(iMultiTransac). It will then immediately pass this transaction object
2235 // to the PSL for processing - before considering any other transactions that have been
2236 // requested, and without completing the multi-transaction request(this is done once
2237 // iMultiTransac has been processed)
2238 buf1 = HBuf8::New(1);
2239 spiBuf = new TConfigSpiBufV01();
2240 if(buf1 == NULL||spiBuf == NULL) {delete buf1;delete spiBuf; return KErrNoMemory;}
2243 if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
2245 CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
2249 tfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
2250 if(tfer == NULL) {delete buf1; delete spiBuf; return KErrNoMemory;}
2252 iMultiTransac = new TIicBusTransaction((TDes8*)spiBuf, tfer);
2253 if(iMultiTransac == NULL) {delete buf1; delete spiBuf; delete tfer; return KErrNoMemory;}
2255 r = ExtractTransData((TUsideTracnDesc*)a2, trans);
2258 CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - ExtractTransData returned %d\n",r));
2261 CLIENT_PRINT(("DChannelIicClient::DoControl invoking (synchronous) QueueTransaction with busId=0x%x, trans=0x%x\n",(TUint32)a1,trans));
2263 r = QueueTransaction((TUint32)a1, trans);
2264 CleanupExtractTrans(trans);
2265 CleanupTransaction(trans);
2266 if((usTrans.iFlags)&KTransactionWithMultiTransc)
2271 delete iMultiTransac;
2275 case(RBusDevIicClient::ECtlIoBlockReqCompletion):
2276 case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
2277 case(RBusDevIicClient::ECtlIoDeRegChan):
2279 // a1 specifies Bus Realisation Config to use
2280 CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
2281 // Use the IIC StaticExtension interface to pass the request to the bus implementation
2282 r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
2285 case(RBusDevIicClient::ECtlIoTestFullDuplexTrans):
2287 // a1 specifies Bus Realisation Config to use
2288 CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
2289 r = DoCreateFullDuplexTransTest((TInt)a2);
2292 case(RBusDevIicClient::ECtlIoPriorityTest):
2294 // a1 specifies Bus Realisation Config to use
2295 CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
2296 r = DoPriorityTest((TUint32)a1);
2300 case(RBusDevIicClient::ECtlIoTracnOne):
2302 // a1 specifies Bus Realisation Config to use
2303 CLIENT_PRINT(("DChannelIicClient::StaticExtension invoking StaticExtension with ctrlIoVal=%d, busId=0x%x\n",aId,(TUint32)a1));
2304 // Use the IIC StaticExtension interface to pass the request to the bus implementation
2305 r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
2306 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("StaticExtension",__LINE__));
2309 // Create then send (synchronously) Transaction One
2310 r = ConstructTransactionOne(iTrans);
2311 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
2312 r = QueueTransaction((TUint32)a1, iTrans);
2313 __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
2314 CleanupTransactionOne(iTrans);
2316 r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
2319 case(RBusDevIicClient::ECtlIoSetTimeOutFlag):
2321 CLIENT_PRINT(("DChannelIicClient::DoControl instruct the bus that it is to simulate a slave timeout"));
2322 // To support testing, function index passed to StaticExtension must be shifted one place to the left
2323 TUint testIndex = ((TUint)RBusDevIicClient::ECtlIoSetTimeOutFlag)<<1;;
2324 r = StaticExtension((TUint32)a1, testIndex, NULL, NULL);
2327 case(RBusDevIicClient::ECtlIoNone):
2329 CLIENT_PRINT(("DChannelIicClient::DoControl Return the bus to its default test state"));
2330 r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
2334 // Support for MasterSlave processing
2336 case(RBusDevIicClient::ECaptureChanSync):
2338 // a1 is a pointer to the TDes8* aConfigHdr
2339 // a2 is a pointer to TInt* parms[2], where:
2340 // parms[0]=(TInt*)aBusId;
2341 // parms[1]=&aChannelId;
2344 r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
2346 break; // Can't proceed if can't access request parameters
2348 TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
2349 CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
2352 CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
2353 return KErrArgument;
2355 if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
2356 return KErrNoMemory;
2357 r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
2363 // Store the address of the user-side variable to update with the ChannelId
2364 iClientChanId=parms[1];
2366 CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
2367 r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
2370 CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
2372 TInt r=Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
2373 (void)r; // Silence the compiler
2378 case(RBusDevIicClient::EReleaseChan):
2380 // a1 represents TInt aChannelId
2381 CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
2382 r = ReleaseChannel((TInt)a1);
2387 case(RBusDevIicClient::EInitSlaveClient):
2389 r=InitSlaveClient();
2393 #ifdef STANDALONE_CHANNEL
2394 case(RBusDevIicClient::ETestIicChannelInlineFunc):
2396 TTestIicChannelInterface channelInterface(DIicBusChannel::EMaster, DIicBusChannel::EI2c, DIicBusChannel::EHalfDuplex);
2397 r = channelInterface.TestInterface();
2404 CLIENT_PRINT(("DChannelIicClient::DoControl - unrecognised value for aId=0x%x\n",aId));
2412 TInt DChannelIicClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
2414 CLIENT_PRINT(("DChannelIicClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
2419 case(RBusDevIicClient::EQTransAsync):
2421 // a1 specifies Bus Realisation Config to use
2422 // a2 is a pointer to TIicBusTransaction
2423 TIicBusTransaction* trans = NULL;
2424 r = ExtractTransData((TUsideTracnDesc*)a2, trans);
2427 CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - ExtractTransData returned %d\n",r));
2430 // Create TIicBusCallback object
2431 TIicBusCallback* cb = new TIicBusCallback(AsyncCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
2432 TTransCbPair* cbPair = new TTransCbPair();
2434 cbPair->iTrans=trans;
2435 // Create an entry in the RPointerArray for TRequestStatus - TIicBusTransaction pairs
2436 TTransStatusPair* pair = new TTransStatusPair();
2439 r=InsertPairs(pair,cbPair);
2442 CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - InsertInOrder returned %d\n",r));
2445 CLIENT_PRINT(("DChannelIicClient::DoRequest invoking (asynchronous) QueueTransaction with busId=0x%x, trans=0x%x, cb=0x%x\n",(TUint32)a1,trans,cb));
2446 r = QueueTransaction((TUint32)a1, trans, cb);
2449 // The transaction was not queued - since it will not be completed asynchronously, need to remove it here
2452 TInt pairIndex=iTransStatArrayByTrans.FindInOrder(pair,TransStatusOrderByTrans);
2453 __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByTrans pairIndex<0",__LINE__));
2454 iTransStatArrayByTrans.Remove(pairIndex);
2455 pairIndex = iTransStatArrayByStatus.FindInOrder(pair,TransStatusOrderByStatus);
2456 __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByStatus pairIndex<0",__LINE__));
2457 iTransStatArrayByStatus.Remove(pairIndex);
2458 pairIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
2459 __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync Cb by Trans pairIndex<0",__LINE__));
2460 iTransCbArrayByTrans.Remove(pairIndex);
2463 Kern::RequestComplete(iClient, aStatus, r);
2466 CleanupExtractTrans(pair->iTrans);
2467 CleanupTransaction(pair->iTrans);
2473 case(RBusDevIicClient::ECtrlIoTestBufReUse):
2476 // a1 specifies Bus Realisation Config to use
2478 // Ensure object pointers are made available
2479 CleanupTransaction(iTrans);
2482 TIicBusCallback* cb = NULL;
2484 // Use default constructor to create an empty transaction
2485 iTrans = new TIicBusTransaction();
2488 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTrans=NULL\n"));
2492 // Create a header for the transaction
2495 r = CreateDefaultSpiBuf(iSpiBuf);
2498 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - CreateDefaultSpiBuf returned %d\n",r));
2502 // Create and add transfer lists for half-duplex and full-duplex entries in the transaction
2505 // Use simple text as payload, 8bit granularity, half-duplex write, full-duplex read (ie payload ignored)
2506 _LIT(halfDuplexText1,"Half Duplex Text 1");
2507 TBuf8<19> halfDuplexBuf_8;
2508 halfDuplexBuf_8.Copy(halfDuplexText1);
2509 iTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf_8);
2512 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTfer=NULL\n"));
2517 _LIT(halfDuplexText2,"Half Duplex Text 2");
2518 TBuf8<19> halfDuplexBuf2_8;
2519 halfDuplexBuf2_8.Copy(halfDuplexText2);
2520 TIicBusTransfer* tempHdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf2_8);
2521 if(tempHdTfer == NULL)
2523 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempHdTfer=NULL\n"));
2528 iTfer->LinkAfter(tempHdTfer);
2533 _LIT(fullDuplexText1,"Full Duplex Text 1");
2534 TBuf8<19> fullDuplexBuf1_8;
2535 fullDuplexBuf1_8.Copy(fullDuplexText1);
2536 iFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf1_8);
2539 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iFdTfer=NULL\n"));
2544 _LIT(fullDuplexText2,"Full Duplex Text 2");
2545 TBuf8<19> fullDuplexBuf2_8;
2546 fullDuplexBuf2_8.Copy(fullDuplexText2);
2547 TIicBusTransfer* tempFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf2_8);
2548 if(tempFdTfer == NULL)
2550 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempFdTfer=NULL\n"));
2555 iFdTfer->LinkAfter(tempFdTfer);
2561 // Add the Header and Transfers to the Transaction
2563 r = iTrans->SetHalfDuplexTrans(iSpiBuf, iTfer);
2566 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetHalfDuplexTrans returned %d\n",r));
2570 r = iTrans->SetFullDuplexTrans(iFdTfer);
2573 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetFullDuplexTrans returned %d\n",r));
2576 // Specify the callback object to use
2579 cb = new TIicBusCallback(TransModifCallback, this, iDfcQue, 5); // 5 arbitrary
2582 CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - cb=NULL\n"));
2587 // Since the transaction is not yet queued, should be able to modify the transfer and transaction content
2588 TestTransModification(iTrans, iTfer, iFdTfer, iSpiBuf);
2590 // Store the relevant data in this object's iTransBufReuseData member
2591 iTransBufReuseData.iTransaction = iTrans;
2592 iTransBufReuseData.iHdTfer = iTfer;
2593 iTransBufReuseData.iFdTfer = iFdTfer;
2594 iTransBufReuseData.iHdr = iSpiBuf;
2595 iTransBufReuseData.iCallback = cb;
2597 // Now queue the transaction. The callback function will re-apply the modification tests and delete the
2598 // objects created here
2599 // If the queueing fails, complete the test here and clean up
2600 r = QueueTransaction((TInt)a1, iTrans, cb);
2603 Kern::RequestComplete(iClient, iStatus, r);
2604 delete iTransBufReuseData.iCallback; // Must do this before deleting the Transaction in CleanupTransaction
2605 CleanupTransaction(iTrans);
2611 CLIENT_PRINT(("DChannelIicClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
2620 // Support for MasterSlave processing
2621 static void MsSlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny* aParam)
2623 CLIENT_PRINT(("> MsSlaveClientCallbackFunc() - aChannelId=0x%x,aReturn=%d,aTrigger=0x%x,aRxWords=0x%x,aTxWords=0x%x,aParam=0x%x\n",aChannelId,aReturn,aTrigger,aRxWords,aTxWords,aParam));
2624 (void)aTxWords; // Unused if CLIENT_PRINT is disabled
2625 (void)aRxWords; // Unused if CLIENT_PRINT is disabled
2626 DChannelIicClient* channel = (DChannelIicClient*)aParam;
2627 CLIENT_PRINT(("MsSlaveClientCallbackFunc() - channel=0x%x\n",channel));
2628 if(aTrigger == EAsyncCaptChan)
2630 CLIENT_PRINT(("MsSlaveClientCallbackFunc: capture channel completed\n"));
2631 // Set iChannelId, and write to user-side variable.
2632 channel->iChannelId=aChannelId;
2633 TInt r=Kern::ThreadRawWrite(channel->iClient,channel->iClientChanId,&aChannelId,sizeof(TInt));
2636 channel->RequestComplete(r); // Inform user of error
2641 CLIENT_PRINT(("\nMsSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
2642 channel->RequestComplete(aReturn); // Inform user of error
2646 void DChannelIicClient::RequestComplete(TInt r)
2648 Kern::RequestComplete(iClient, iStatus, r);
2652 TInt DChannelIicClient::InitSlaveClient()
2654 iNotif = new TIicBusSlaveCallback(MsSlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
2657 CLIENT_PRINT(("> DChannelIicClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
2658 return KErrNoMemory;