kerneltest/e32test/iic/iic_psl/iic_client.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test/iic/iic_client.cpp
       
    15 // Simulated (kernel-side) client of IIC Platform Independent Layer (PIL)
       
    16 //
       
    17 #include <kernel/kern_priv.h>		// for DThread, TDfc
       
    18 #ifdef STANDALONE_CHANNEL
       
    19 #include <drivers/iic_transaction.h>
       
    20 #else
       
    21 #include <drivers/iic.h>
       
    22 #endif
       
    23 #include "../t_iic.h"
       
    24 #ifdef STANDALONE_CHANNEL
       
    25 #include <drivers/iic_channel.h>
       
    26 #include "i2c.h"
       
    27 #include "spi.h"
       
    28 #endif
       
    29 
       
    30 #ifdef LOG_CLIENT
       
    31 #define CLIENT_PRINT(str) Kern::Printf str
       
    32 #else
       
    33 #define CLIENT_PRINT(str)
       
    34 #endif
       
    35 
       
    36 const TInt KIicClientThreadPriority = 24;
       
    37 const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest ... for MasterSlave functionality
       
    38 
       
    39 const TInt KMaxNumChannels = 3;	// 1 SPI and 2 I2C
       
    40 
       
    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
       
    44 
       
    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)
       
    51 
       
    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};
       
    57 #else
       
    58 const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
       
    59 #endif
       
    60 #define CHANNEL_TYPE_I2C(n) (KChannelTypeArrayI2c[n])
       
    61 #define CHANNEL_DUPLEX_I2C(n) (DIicBusChannel::EHalfDuplex)
       
    62 #define BUS_TYPE_I2C (DIicBusChannel::EI2c)
       
    63 
       
    64 const TInt8 KSpiChannelNumBase = 1;	// Arbitrary, real platform may consult the Configuration Repository
       
    65 									// Note limit of 5 bit representation (0-31)
       
    66 
       
    67 LOCAL_C TInt8 AssignChanNumSpi()
       
    68 	{
       
    69 	static TInt8 iBaseChanNumSpi = KSpiChannelNumBase;
       
    70 	CLIENT_PRINT(("SPI AssignChanNum - on entry, iBaseCanNum = 0x%x\n",iBaseChanNumSpi));
       
    71 	return iBaseChanNumSpi++; // Arbitrary, for illustration
       
    72 	}
       
    73 
       
    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)
       
    77 
       
    78 #else
       
    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
       
    81 #endif
       
    82 
       
    83 LOCAL_C TInt8 AssignChanNumI2c()
       
    84 	{
       
    85 	static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
       
    86 	CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
       
    87 	return iBaseChanNumI2c++; // Arbitrary, for illustration
       
    88 	}
       
    89 
       
    90 class DIicClientChan : public DBase
       
    91 	{
       
    92 public:
       
    93 	DIicClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TUint8 aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
       
    94 	~DIicClientChan();
       
    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;};
       
   100 private:
       
   101 	TInt iChanNumber;
       
   102 	TUint8 iChanType;
       
   103 	DIicBusChannel* iChan;
       
   104 	};
       
   105 
       
   106 DIicClientChan::~DIicClientChan()
       
   107 	{
       
   108 	delete iChan;
       
   109 	}
       
   110 
       
   111 #endif /*STANDALONE_CHANNEL*/
       
   112 
       
   113 
       
   114 #ifdef STANDALONE_CHANNEL
       
   115 _LIT(KLddRootName,"iic_client_ctrless");
       
   116 #else
       
   117 _LIT(KLddRootName,"iic_client");
       
   118 #endif
       
   119 _LIT(KIicClientThreadName,"IicClientLddThread");
       
   120 
       
   121 struct TCapsIicClient
       
   122     {
       
   123     TVersion version;
       
   124     };
       
   125 
       
   126 struct TTransStatusPair
       
   127 	{
       
   128 	TRequestStatus* iReq;
       
   129 	TIicBusTransaction* iTrans;
       
   130 	};
       
   131 
       
   132 struct TTransCbPair
       
   133 	{
       
   134 	TIicBusTransaction* iTrans;
       
   135 	TIicBusCallback* iCb;
       
   136 	};
       
   137 
       
   138 struct TExtractInfo
       
   139     {
       
   140     TExtractInfo(){iBufPtr = NULL; iTfer = NULL;}
       
   141     ~TExtractInfo(){delete iBufPtr; delete iTfer;}
       
   142     TDes8* iBufPtr;
       
   143     TIicBusTransfer* iTfer;
       
   144     TIicBusTransaction* iTrans;
       
   145     };
       
   146 
       
   147 struct TTransBufReuseData
       
   148 	{
       
   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;
       
   154 	TDes8* iHdr;
       
   155 	// Pointer to callback object (for cleanup)
       
   156 	TIicBusCallback* iCallback;
       
   157 	};
       
   158 
       
   159 class DDeviceIicClient : public DLogicalDevice
       
   160     {
       
   161     public:
       
   162     /**
       
   163      * The constructor
       
   164      */
       
   165     DDeviceIicClient();
       
   166     /**
       
   167      * The destructor
       
   168      */
       
   169     ~DDeviceIicClient();
       
   170     /**
       
   171      * Second stage constructor - install the device
       
   172      */
       
   173     virtual TInt Install();
       
   174     /**
       
   175      * Get the Capabilites of the device
       
   176      * @param aDes descriptor that will contain the returned capibilites
       
   177      */
       
   178     virtual void GetCaps(TDes8 &aDes) const;
       
   179     /**
       
   180      * Create a logical channel to the device
       
   181      */
       
   182     virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   183 
       
   184 	public:
       
   185     };
       
   186 
       
   187 #ifdef STANDALONE_CHANNEL
       
   188 /*This class is used to test the set and get inline functions
       
   189  *  of DIicBusChannel Interface.
       
   190  * */
       
   191 class TTestIicChannelInterface: public DIicBusChannel
       
   192 {
       
   193 public:
       
   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();
       
   199 private:
       
   200     TBool TestChannelType(DIicBusChannel::TChannelType aType );
       
   201     TBool TestBusType(DIicBusChannel::TBusType aType );
       
   202     TBool TestDuplexType(DIicBusChannel::TChannelDuplex aType );
       
   203 };
       
   204 
       
   205 TTestIicChannelInterface::TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex)
       
   206         : DIicBusChannel(aChannelType, aBusType, aChanDuplex)
       
   207     {}
       
   208 
       
   209 TBool TTestIicChannelInterface::TestChannelType(DIicBusChannel::TChannelType aType)
       
   210     {
       
   211     CLIENT_PRINT(("Setting channel type 0x%x\n", aType));
       
   212     SetChannelType(aType);
       
   213     if(aType != ChannelType())
       
   214         {
       
   215         CLIENT_PRINT(("ERROR: Mismatch, looking for channel 0x%x but found 0x%x\n", aType, ChannelType()));
       
   216         return EFalse;
       
   217         }
       
   218     else
       
   219         {
       
   220         CLIENT_PRINT(("Looking for channel 0x%x and found 0x%x\n", aType, ChannelType()));
       
   221         }
       
   222     return ETrue;
       
   223     }
       
   224 
       
   225 TBool TTestIicChannelInterface::TestBusType(DIicBusChannel::TBusType aType)
       
   226     {
       
   227     CLIENT_PRINT(("Setting Bus type 0x%x\n", aType));
       
   228     SetBusType(aType);
       
   229     if(aType != BusType())
       
   230         {
       
   231         CLIENT_PRINT(("ERROR: Mismatch, looking for Bus 0x%x but found 0x%x\n", aType, BusType()));
       
   232         return EFalse;
       
   233         }
       
   234     else
       
   235         {
       
   236         CLIENT_PRINT(("Looking for Bus 0x%x and found 0x%x\n", aType, BusType()));
       
   237         }    
       
   238     return ETrue;   
       
   239     }
       
   240 
       
   241 TBool TTestIicChannelInterface::TestDuplexType(DIicBusChannel::TChannelDuplex aType)
       
   242     {
       
   243     CLIENT_PRINT(("Setting duplex channel type 0x%x\n", aType));
       
   244     SetChannelType(aType);
       
   245     if(aType != ChannelDuplex())
       
   246         {
       
   247         CLIENT_PRINT(("ERROR: Mismatch, looking for duplex channel 0x%x but found 0x%x\n", aType, ChannelDuplex()));
       
   248         return EFalse;
       
   249         }
       
   250     else
       
   251         {
       
   252         CLIENT_PRINT(("Looking for Duplex Channel 0x%x and found 0x%x\n", aType, ChannelDuplex()));
       
   253         }    
       
   254     return ETrue;   
       
   255     }
       
   256 
       
   257 TInt TTestIicChannelInterface::TestInterface()
       
   258     {
       
   259     
       
   260     RArray <DIicBusChannel::TChannelType> chtype;
       
   261     RArray <DIicBusChannel::TBusType> bustype;
       
   262     RArray <DIicBusChannel::TChannelDuplex> dutype;
       
   263 
       
   264     chtype.Append(DIicBusChannel::EMaster);
       
   265     chtype.Append(DIicBusChannel::ESlave);
       
   266     chtype.Append(DIicBusChannel::EMasterSlave);
       
   267     
       
   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);
       
   273     
       
   274     dutype.Append(DIicBusChannel::EHalfDuplex);
       
   275     dutype.Append(DIicBusChannel::EFullDuplex);
       
   276       
       
   277     int result = KErrNone;
       
   278     int count = chtype.Count();
       
   279     int i=0;
       
   280     
       
   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)
       
   284         {
       
   285         if(!TestChannelType(chtype[i]))
       
   286             {
       
   287             result = KErrGeneral;
       
   288             break;
       
   289             }
       
   290         }
       
   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)
       
   293         {
       
   294         if(!TestChannelType(chtype[i]))
       
   295             {
       
   296             result = KErrGeneral;
       
   297             break;
       
   298             }
       
   299         }
       
   300     
       
   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)
       
   305         {
       
   306         if(!TestBusType(bustype[i]))
       
   307             {
       
   308             result = KErrGeneral;
       
   309             break;
       
   310             }
       
   311         }
       
   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)
       
   314         {
       
   315         if(!TestBusType(bustype[i]))
       
   316             {
       
   317             result = KErrGeneral;
       
   318             break;
       
   319             }
       
   320         }
       
   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)
       
   325         {
       
   326         if(!TestDuplexType(dutype[i]))
       
   327             {
       
   328             result = KErrGeneral;
       
   329             break;
       
   330             }
       
   331         }
       
   332     CLIENT_PRINT(("\nCheck Channel Duplex setting from higher bit number to lower, reverse enum.\n"));        
       
   333     for(i = count-1; i >= 0; --i)
       
   334         {
       
   335         if(!TestDuplexType(dutype[i]))
       
   336             {
       
   337             result = KErrGeneral;
       
   338             break;
       
   339             }
       
   340         }
       
   341     chtype.Close();
       
   342     dutype.Close();
       
   343     bustype.Close();
       
   344     return result;
       
   345     }
       
   346 #endif //STANDALONE_CHANNEL
       
   347 
       
   348 class DChannelIicClient : public DLogicalChannel
       
   349     {
       
   350     public:
       
   351     DChannelIicClient();
       
   352     ~DChannelIicClient();
       
   353 
       
   354 	TInt CleanupExtractTrans(TIicBusTransaction *aTrans);
       
   355 
       
   356 	TInt InitIicClient();
       
   357 
       
   358     virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
       
   359 
       
   360     protected:
       
   361     virtual void HandleMsg(TMessageBase* aMsg);	// Note: this is a pure virtual in DLogicalChannel
       
   362 
       
   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!
       
   366 
       
   367 	void TestTransModification(TIicBusTransaction* aTransaction, // public to be accessed by callback
       
   368 							  TIicBusTransfer* aHdTfer,
       
   369 							  TIicBusTransfer* aFdTfer,
       
   370 							  TDes8* aHdr);
       
   371 #ifdef STANDALONE_CHANNEL
       
   372     public:
       
   373     static TInt OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry);
       
   374 #endif
       
   375 	private:
       
   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);
       
   385 
       
   386 
       
   387 	TInt DeleteFullDuplexTest(TIicBusTransaction *aTrans);
       
   388 
       
   389 	TInt DoCreateFullDuplexTransTest(TInt aTestType);
       
   390 
       
   391 	TInt DoPriorityTest(TInt aBusId);
       
   392 	TInt ConstructTransactionOne(TIicBusTransaction*& aTrans);
       
   393 	void CleanupTransactionOne(TIicBusTransaction*& aTrans);
       
   394 
       
   395 
       
   396 	TInt InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair);
       
   397 
       
   398 	TInt CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf);
       
   399 
       
   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);
       
   406 	public:
       
   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);}
       
   411 
       
   412 	void CleanupTransaction(TIicBusTransaction*& aTrans); // public for access by callback
       
   413 
       
   414 	static TIicBusTransaction* MultiTranscCallbackFunc(TIicBusTransaction* aTrans, TAny* aParam);
       
   415 
       
   416 	static void TransModifCallback(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam);
       
   417 
       
   418 	private:
       
   419 	TDynamicDfcQue* iDfcQue;
       
   420 
       
   421 	DMutex* iArrayMutex;		// used to protect array of channels
       
   422 	DSemaphore* iChanArrWrtSem;	// used to synchronise write access to iChannelArray
       
   423 
       
   424 	// Used for Transaction One
       
   425 	HBuf8* buf1;
       
   426 	HBuf8* buf2;
       
   427 	HBuf8* buf3;
       
   428 	HBuf8* buf4;
       
   429 	HBuf8* buf5;
       
   430 	HBuf8* buf6;
       
   431 	TIicBusTransfer* tfer1;
       
   432 	TIicBusTransfer* tfer2;
       
   433 	TIicBusTransfer* tfer3;
       
   434 	TIicBusTransfer* tfer4;
       
   435 	TIicBusTransfer* tfer5;
       
   436 	TIicBusTransfer* tfer6;
       
   437 	TIicBusTransfer* tfer7;
       
   438 	HBuf8* header;
       
   439 	HBuf8* header2;
       
   440 	HBuf8* header3;
       
   441 	HBuf8* header4;
       
   442 	HBuf8* header5;
       
   443 	HBuf8* headerBlock;
       
   444 	TConfigSpiBufV01* spiHeader;
       
   445 
       
   446 
       
   447 	static TIicBusTransaction* iMultiTransac;
       
   448 
       
   449 	// Used for simple transactions
       
   450 	TIicBusTransaction* iTrans;
       
   451 	TConfigSpiBufV01* iSpiBuf;
       
   452 	TConfigI2cBufV01* iI2cBuf;
       
   453 	TIicBusTransfer* iTfer;
       
   454 	TIicBusTransactionPreamble* iTransPreamble;
       
   455 	TIicBusTransfer* iFdTfer;
       
   456 
       
   457 	public:
       
   458 	DThread* iClient;
       
   459 	RPointerArray<TTransStatusPair> iTransStatArrayByTrans;
       
   460 	RPointerArray<TTransStatusPair> iTransStatArrayByStatus;
       
   461 	RPointerArray<TTransCbPair> iTransCbArrayByTrans;
       
   462 	RPointerArray<TExtractInfo> iExtractInfoArray;
       
   463 
       
   464 	// Support for Preamble testing
       
   465 	TRequestStatus* iPreambleStatus;
       
   466 	TRequestStatus* iMultiTranscStatus;
       
   467 
       
   468 	// Support for buffer re-use testing
       
   469 	TTransBufReuseData iTransBufReuseData;
       
   470 
       
   471 	// Support for MasterSlave processing
       
   472 	private:
       
   473 	TInt InitSlaveClient();
       
   474 
       
   475 	private:
       
   476 	HBuf8* iConfigHdr;
       
   477 	TRequestStatus* iStatus;
       
   478 
       
   479 	public:
       
   480 	void RequestComplete(TInt r);
       
   481 
       
   482 	public:
       
   483 	TIicBusSlaveCallback* iNotif;		// public to be accessible by callback
       
   484 	TInt iChannelId;				// public to be accessible by callback
       
   485 	TInt* iClientChanId;
       
   486 
       
   487 #ifdef STANDALONE_CHANNEL
       
   488 	//Used to store the captured channel
       
   489 	struct TCapturedChannel
       
   490         {
       
   491         DIicClientChan* iChanPtr;
       
   492         TInt iChannelId;
       
   493         };
       
   494 	TCapturedChannel iCapturedChannel;
       
   495 #endif
       
   496 	};
       
   497 
       
   498 DDeviceIicClient::DDeviceIicClient()
       
   499 // Constructor
       
   500     {
       
   501 	CLIENT_PRINT(("> DDeviceIicClient::DDeviceIicClient()"));
       
   502     __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::DDeviceIicClient()"));
       
   503     iParseMask=0;		// No info, no PDD, no Units
       
   504     iUnitsMask=0;
       
   505     iVersion=TVersion(KIicClientMajorVersionNumber,
       
   506 		      KIicClientMinorVersionNumber,
       
   507 		      KIicClientBuildVersionNumber);
       
   508     }
       
   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)
       
   512 	{
       
   513 	TUint8 l=(TUint8)aMatch.GetChanNum();
       
   514 	TUint8 r=(TUint8)aEntry.GetChanNum();
       
   515 	if(l<r)
       
   516 		return -1;
       
   517 	else if(l>r)
       
   518 		return 1;
       
   519 	else
       
   520 		return 0;
       
   521 	}
       
   522 // global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
       
   523 TLinearOrder<DIicClientChan> EntryOrder(DChannelIicClient::OrderEntries);
       
   524 
       
   525 // Store all the channels created by the client
       
   526 RPointerArray<DIicClientChan> ChannelArray;
       
   527 #endif /*STANDALONE_CHANNEL*/
       
   528 
       
   529 DDeviceIicClient::~DDeviceIicClient()
       
   530     {
       
   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();
       
   536 #endif
       
   537 	}
       
   538 
       
   539 TInt DDeviceIicClient::Install()
       
   540 // Install the device driver.
       
   541     {
       
   542 	CLIENT_PRINT(("> DDeviceIicClient::Install()"));
       
   543     __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::Install()"));
       
   544     return(SetName(&KLddRootName));
       
   545     }
       
   546 
       
   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)
       
   551 	{
       
   552 	TUint l=(TUint)(aMatch.iTrans);
       
   553 	TUint r=(TUint)(aEntry.iTrans);
       
   554 	if(l>r)
       
   555 		return -1;
       
   556 	else if(l<r)
       
   557 		return 1;
       
   558 	else
       
   559 		return 0;
       
   560 	}
       
   561 TLinearOrder<TTransStatusPair> TransStatusOrderByTrans(OrderEntriesByTrans);
       
   562 
       
   563 TInt OrderEntriesByStatus(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
       
   564 	{
       
   565 	TUint l=(TUint)(aMatch.iReq);
       
   566 	TUint r=(TUint)(aEntry.iReq);
       
   567 	if(l>r)
       
   568 		return -1;
       
   569 	else if(l<r)
       
   570 		return 1;
       
   571 	else
       
   572 		return 0;
       
   573 	}
       
   574 TLinearOrder<TTransStatusPair> TransStatusOrderByStatus(OrderEntriesByStatus);
       
   575 
       
   576 // Auxilliary function to track callback objects assigned to asynchronous transactions
       
   577 TInt OrderCbEntriesByTrans(const TTransCbPair& aMatch, const TTransCbPair& aEntry)
       
   578 	{
       
   579 	TUint l=(TUint)(aMatch.iTrans);
       
   580 	TUint r=(TUint)(aEntry.iTrans);
       
   581 	if(l>r)
       
   582 		return -1;
       
   583 	else if(l<r)
       
   584 		return 1;
       
   585 	else
       
   586 		return 0;
       
   587 	}
       
   588 TLinearOrder<TTransCbPair> TransCbOrderByTrans(OrderCbEntriesByTrans);
       
   589 
       
   590 TInt OrderExtractInfoByTrans(const TExtractInfo& aMatch, const TExtractInfo& aEntry)
       
   591     {
       
   592     TUint l=(TUint)(aMatch.iTrans);
       
   593     TUint r=(TUint)(aEntry.iTrans);
       
   594     if(l>r)
       
   595         return -1;
       
   596     else if(l<r)
       
   597         return 1;
       
   598     else
       
   599         return 0;
       
   600     }
       
   601 TLinearOrder<TExtractInfo> ExtractInfoOrderByTrans(OrderExtractInfoByTrans);
       
   602 
       
   603 
       
   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
       
   607 
       
   608 TInt DChannelIicClient::InitIicClient()
       
   609 	{
       
   610 	TInt r = Kern::MutexCreate(iArrayMutex,KLitArrayMutexName,IIC_CLIENT_MUTEX_ORDER);
       
   611 	if(r!=KErrNone)
       
   612 		return r;
       
   613 	r = Kern::SemaphoreCreate(iChanArrWrtSem,KLitArraySemName,1); // Initial count of one allows first wait to be non-blocking
       
   614 	if(r!=KErrNone)
       
   615 		iArrayMutex->Close(NULL);
       
   616 
       
   617 	return r;
       
   618 	}
       
   619 
       
   620 TInt DChannelIicClient::InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair)
       
   621 	{
       
   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 ));
       
   624 	TInt r = KErrNone;
       
   625 
       
   626 	GetWriteAccess();
       
   627 	Lock();
       
   628 
       
   629 	if((r = iTransStatArrayByTrans.InsertInOrder(aPair,TransStatusOrderByTrans)) == KErrNone)
       
   630 		{
       
   631 		if((r = iTransStatArrayByStatus.InsertInOrder(aPair,TransStatusOrderByStatus)) == KErrNone)
       
   632 			{
       
   633 			if((r = iTransCbArrayByTrans.InsertInOrder(aCbPair,TransCbOrderByTrans))!=KErrNone)
       
   634 				{
       
   635 				CLIENT_PRINT(("DChannelIicClient::InsertPairs, aCbPair=0x%x InsertInOrder(status) returned %d\n",aCbPair,r));
       
   636 				}
       
   637 			}
       
   638 		else
       
   639 			{
       
   640 			CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(status) returned %d\n",aPair,r));
       
   641 			}
       
   642 		}
       
   643 	else
       
   644 		{
       
   645 		CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(trans) returned %d\n",aPair,r));
       
   646 		}
       
   647 	FreeWriteAccess();
       
   648 	Unlock();
       
   649 	return r;
       
   650 	}
       
   651 
       
   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*/)
       
   654 	{
       
   655 	//do nothing
       
   656 	}
       
   657 
       
   658 static void AsyncCallbackFunc(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam)
       
   659 	{
       
   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));
       
   664 
       
   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();
       
   669 	channel->Lock();
       
   670 	TInt pairIndex = (channel->iTransStatArrayByTrans).FindInOrder(searchPair,TransStatusOrderByTrans);
       
   671 	delete searchPair;
       
   672 	if(pairIndex<0)
       
   673 		{
       
   674 		CLIENT_PRINT(("AsyncCallbackFunc() - (trans) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
       
   675 		return;
       
   676 		}
       
   677 	TTransStatusPair* pairPtr = (channel->iTransStatArrayByTrans)[pairIndex];
       
   678 	TRequestStatus* status = pairPtr->iReq;
       
   679 
       
   680 	// Now remove the TTransStatusPair objects in iTransStatArrayByTrans, iTransStatArrayByStatus
       
   681 	(channel->iTransStatArrayByTrans).Remove(pairIndex);
       
   682 	pairIndex = (channel->iTransStatArrayByStatus).FindInOrder(pairPtr,TransStatusOrderByStatus);
       
   683 	if(pairIndex<0)
       
   684 		{
       
   685 		CLIENT_PRINT(("AsyncCallbackFunc() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndex,status));
       
   686 		return;
       
   687 		}
       
   688 	(channel->iTransStatArrayByStatus).Remove(pairIndex);
       
   689 
       
   690 	// Now remove the TTransCbPair object in iTransCbArrayByTrans
       
   691 	TTransCbPair* SearchCbPair = new TTransCbPair();
       
   692 	SearchCbPair->iTrans = aTrans;
       
   693 	pairIndex = (channel->iTransCbArrayByTrans).FindInOrder(SearchCbPair,TransCbOrderByTrans);
       
   694 	delete SearchCbPair;
       
   695 	if(pairIndex<0)
       
   696 		{
       
   697 		CLIENT_PRINT(("AsyncCallbackFunc() - (cb) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
       
   698 		return;
       
   699 		}
       
   700 	TTransCbPair* cbPair = (channel->iTransCbArrayByTrans)[pairIndex];
       
   701 	(channel->iTransCbArrayByTrans).Remove(pairIndex);
       
   702 	delete cbPair->iCb;
       
   703 	delete cbPair;
       
   704 	channel->FreeWriteAccess();
       
   705 	channel->Unlock();
       
   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);
       
   711 	delete pairPtr;
       
   712 	}
       
   713 
       
   714 
       
   715 void DDeviceIicClient::GetCaps(TDes8& aDes) const
       
   716 // Return the IicClient capabilities.
       
   717     {
       
   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);
       
   724     }
       
   725 
       
   726 
       
   727 TInt DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)
       
   728 // Create a channel on the device.
       
   729     {
       
   730 	CLIENT_PRINT(("> DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)"));
       
   731 	if(iOpenChannels>=KMaxNumChannels)
       
   732 		return KErrOverflow;
       
   733     aChannel=new DChannelIicClient;
       
   734     return aChannel?KErrNone:KErrNoMemory;
       
   735     }
       
   736 
       
   737 #ifdef STANDALONE_CHANNEL
       
   738 
       
   739 TInt GetChanPtr(const TInt aBusId, TInt &aIndex, DIicClientChan*& aChan)
       
   740 	{
       
   741     __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
       
   742 	TInt32 chanId;
       
   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);
       
   748 	if(aIndex >= 0)
       
   749 		{
       
   750 		aChan = ChannelArray[aIndex];
       
   751 		r = KErrNone;
       
   752 		}
       
   753 
       
   754 	__KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, chanPtr=0x%x, index=%d\n",aChan,aIndex));
       
   755 	return r;
       
   756 	}
       
   757 #endif
       
   758 
       
   759 DECLARE_STANDARD_LDD()
       
   760 	{
       
   761 	//If in STANDALONE_CHANNEL mode, the client creates a list of channels
       
   762 #ifdef STANDALONE_CHANNEL
       
   763 	DIicClientChan* aClientChan;
       
   764 	TInt r = KErrNone;
       
   765 	DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
       
   766 	TInt i;
       
   767 	for(i=0; i<NUM_CHANNELS_SPI; i++)
       
   768 		{
       
   769 		CLIENT_PRINT(("\n"));
       
   770 #if defined(MASTER_MODE)
       
   771 		if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::EMaster))
       
   772 			{
       
   773 			chan=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
       
   774 			if(!chan)
       
   775 			    {
       
   776 			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
       
   777 				return NULL;
       
   778 			    }
       
   779 			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
       
   780 			if(((DSimulatedIicBusChannelMasterSpi*)chan)->Create()!=KErrNone)
       
   781 			    {
       
   782 			    delete chan;
       
   783 				return NULL;
       
   784 			    }
       
   785 			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMaster);
       
   786             if(!aClientChan)
       
   787                 {
       
   788                 delete chan;
       
   789                 return NULL;
       
   790                 }
       
   791             r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   792             if(r!=KErrNone)
       
   793                 {
       
   794                 delete chan;
       
   795                 delete aClientChan;
       
   796                 break;
       
   797                 }
       
   798 			}
       
   799 #endif
       
   800 #if defined(MASTER_MODE) && defined(SLAVE_MODE)
       
   801 		if(CHANNEL_TYPE_SPI(i) == DIicBusChannel::EMasterSlave)
       
   802 			{
       
   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));
       
   806 			if(!chanM)
       
   807 				return NULL;
       
   808 
       
   809 			chanS=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
       
   810 			if(!chanS)
       
   811 			    {
       
   812 			    delete chanM;
       
   813 				return NULL;
       
   814 			    }
       
   815 			chan=new DIicBusChannelMasterSlave(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i),(DSimulatedIicBusChannelMasterSpi*)chanM,(DSimulatedIicBusChannelSlaveSpi*)chanS); // Generic implementation
       
   816 			if(!chan)
       
   817 			    {
       
   818 			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
       
   819 			    delete chanM;
       
   820 			    delete chanS;
       
   821 				return NULL;
       
   822 			    }
       
   823 			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
       
   824 			if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
       
   825 			    {
       
   826 			    delete chanM;
       
   827 			    delete chanS;
       
   828 			    delete chan;
       
   829 				return NULL;
       
   830 			    }
       
   831 			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMasterSlave);
       
   832 			if(!aClientChan)
       
   833 			    {
       
   834 			    delete chanM;
       
   835 			    delete chanS;
       
   836 			    delete chan;
       
   837 			    return NULL;
       
   838 			    }
       
   839             r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   840             if(r!=KErrNone)
       
   841                 {
       
   842                 delete chanM;
       
   843                 delete chanS;
       
   844                 delete chan;
       
   845                 delete aClientChan;
       
   846                 break;
       
   847                 }
       
   848 			}
       
   849 #endif
       
   850 #if defined(SLAVE_MODE)
       
   851 		if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::ESlave))
       
   852 			{
       
   853 			chan=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
       
   854 			if(!chan)
       
   855 			    {
       
   856 			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
       
   857 				return NULL;
       
   858 			    }
       
   859 			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
       
   860 			if(((DSimulatedIicBusChannelSlaveSpi*)chan)->Create()!=KErrNone)
       
   861 			    {
       
   862 			    delete chan;
       
   863 				return NULL;
       
   864 			    }
       
   865 			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::ESlave);
       
   866             if(!aClientChan)
       
   867                 {
       
   868                 delete chan;
       
   869                 return NULL;
       
   870                 }
       
   871             r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   872             if(r!=KErrNone)
       
   873                 {
       
   874                 delete chan;
       
   875                 delete aClientChan;
       
   876                 break;
       
   877                 }
       
   878 			}
       
   879 #endif
       
   880 #if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
       
   881 #error I2C mode not defined as Master, Slave nor Master-Slave
       
   882 #endif
       
   883 		}
       
   884 
       
   885 	for(i=0; i<NUM_CHANNELS_I2C; i++)
       
   886 			{
       
   887 			CLIENT_PRINT(("\n"));
       
   888 	#if defined(MASTER_MODE)
       
   889 			if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::EMaster))
       
   890 				{
       
   891 				chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
       
   892 				if(!chan)
       
   893 				    {
       
   894 				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
       
   895 					return NULL;
       
   896 				    }
       
   897 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   898 				if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
       
   899 				    {
       
   900 				    delete chan;
       
   901 					return NULL;
       
   902 					}
       
   903 				aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
       
   904 				if(!aClientChan)
       
   905 				    {
       
   906 				    delete chan;
       
   907 				    return NULL;
       
   908 				    }
       
   909                 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   910                 if(r!=KErrNone)
       
   911                     {
       
   912                     delete chan;
       
   913                     delete aClientChan;
       
   914                     break;
       
   915                     }
       
   916 				}
       
   917 	#endif
       
   918 	#if defined(MASTER_MODE) && defined(SLAVE_MODE)
       
   919 			if(CHANNEL_TYPE_I2C(i) == DIicBusChannel::EMasterSlave)
       
   920 				{
       
   921 				chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
       
   922 				if(!chanM)
       
   923 					return NULL;
       
   924 
       
   925 				chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
       
   926 				if(!chanS)
       
   927 				    {
       
   928 				    delete chanM;
       
   929 					return NULL;
       
   930 				    }
       
   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
       
   934 				if(!chan)
       
   935 				    {
       
   936 				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
       
   937 				    delete chanM;
       
   938 				    delete chanS;
       
   939 					return NULL;
       
   940 				    }
       
   941 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   942 				if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
       
   943 				    {
       
   944 				    delete chanM;
       
   945 				    delete chanS;
       
   946 				    delete chan;
       
   947 					return NULL;
       
   948 				    }
       
   949 			    aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
       
   950                 if(!aClientChan)
       
   951                     {
       
   952                     delete chanM;
       
   953                     delete chanS;
       
   954                     delete chan;
       
   955                     return NULL;
       
   956                     }
       
   957                 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   958                 if(r!=KErrNone)
       
   959                     {
       
   960                     delete chanM;
       
   961                     delete chanS;
       
   962                     delete chan;
       
   963                     delete aClientChan;
       
   964                     break;
       
   965                     }
       
   966 				}
       
   967 	#endif
       
   968 	#if defined(SLAVE_MODE)
       
   969 			if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::ESlave))
       
   970 				{
       
   971 				chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
       
   972 				if(!chan)
       
   973 				    {
       
   974 				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
       
   975 					return NULL;
       
   976 				    }
       
   977 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   978 				if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
       
   979 				    {
       
   980 				    delete chan;
       
   981 					return NULL;
       
   982 				    }
       
   983 			    aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
       
   984                 if(!aClientChan)
       
   985                     {
       
   986                     delete chan;
       
   987                     return NULL;
       
   988                     }
       
   989                 r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
       
   990                 if(r!=KErrNone)
       
   991                     {
       
   992                     delete chan;
       
   993                     delete aClientChan;
       
   994                     break;
       
   995                     }
       
   996 				}
       
   997 	#endif
       
   998 	#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
       
   999 	#error I2C mode not defined as Master, Slave nor Master-Slave
       
  1000 	#endif
       
  1001 			}
       
  1002 
       
  1003 #endif
       
  1004 	return new DDeviceIicClient;
       
  1005 	}
       
  1006 
       
  1007 
       
  1008 
       
  1009 DChannelIicClient::DChannelIicClient()
       
  1010 // Constructor
       
  1011     {
       
  1012 	CLIENT_PRINT(("> DChannelIicClient::DChannelIicClient()"));
       
  1013     iClient=&Kern::CurrentThread();
       
  1014 	// Increase the DThread's ref count so that it does not close without us
       
  1015 	iClient->Open();
       
  1016     }
       
  1017 
       
  1018 DChannelIicClient::~DChannelIicClient()
       
  1019 // Destructor
       
  1020     {
       
  1021 	CLIENT_PRINT(("> DChannelIicClient::~DChannelIicClient()"));
       
  1022     __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelIicClient::~DChannelIicClient()"));
       
  1023     delete iNotif;
       
  1024     iArrayMutex->Close(NULL);
       
  1025     iChanArrWrtSem->Close(NULL);
       
  1026 	iDfcQue->Destroy();
       
  1027 	// decrement the DThread's reference count
       
  1028 	Kern::SafeClose((DObject*&)iClient, NULL);
       
  1029 
       
  1030     iTransStatArrayByTrans.Reset();
       
  1031     iTransStatArrayByStatus.Reset();
       
  1032     iTransCbArrayByTrans.Reset();
       
  1033 	iExtractInfoArray.Reset();
       
  1034 	}
       
  1035 
       
  1036 
       
  1037 TInt DChannelIicClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
  1038 	{
       
  1039 	CLIENT_PRINT(("> DChannelIicClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
       
  1040 	TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicClientThreadPriority,KIicClientThreadName);
       
  1041 	if(r!=KErrNone)
       
  1042 		return r;
       
  1043 	SetDfcQ(iDfcQue);
       
  1044 	iMsgQ.Receive();
       
  1045 
       
  1046 	r = InitIicClient();
       
  1047 	return r;
       
  1048 	}
       
  1049 
       
  1050 void DChannelIicClient::HandleMsg(TMessageBase* aMsg)
       
  1051 	{
       
  1052 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
  1053     TInt id=m.iValue;
       
  1054 
       
  1055 	CLIENT_PRINT((" >ldd: DChannelIicClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
       
  1056 
       
  1057 	if (id == (TInt)ECloseMsg)
       
  1058 		{
       
  1059 	    iMsgQ.iMessage->Complete(KErrNone,EFalse);
       
  1060 		return;
       
  1061 		}
       
  1062     else if (id == KMaxTInt)
       
  1063 		{
       
  1064 		DoCancel(m.Int0());
       
  1065 		m.Complete(KErrNone,ETrue);
       
  1066 		return;
       
  1067 		}
       
  1068 
       
  1069     if (id<0)
       
  1070 		{
       
  1071 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
  1072 		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
       
  1073 		if (r!=KErrNone)
       
  1074 			{
       
  1075 	    	Kern::RequestComplete(iClient, pS, r);
       
  1076 			}
       
  1077 		m.Complete(KErrNone,ETrue);
       
  1078 		}
       
  1079     else
       
  1080 		{
       
  1081 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
  1082 		m.Complete(r,ETrue);
       
  1083 		}
       
  1084 	}
       
  1085 
       
  1086 TInt DChannelIicClient::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback/*NULL*/)
       
  1087 	{
       
  1088 	TInt r = KErrNone;
       
  1089 #ifndef STANDALONE_CHANNEL
       
  1090 	if(!aCallback)
       
  1091 		r = IicBus::QueueTransaction(aBusId, aTransaction);
       
  1092 	else
       
  1093 		r = IicBus::QueueTransaction(aBusId, aTransaction, aCallback);
       
  1094 #else
       
  1095 	__KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
       
  1096 	if(!aTransaction)
       
  1097 		{
       
  1098 		return KErrArgument;
       
  1099 		}
       
  1100 
       
  1101 	// Get a pointer to the channel
       
  1102 	TInt dumInt = 0;
       
  1103 	DIicClientChan* chanPtr = NULL;
       
  1104 	r = GetChanPtr(aBusId, dumInt, chanPtr);
       
  1105 	if(r == KErrNone)
       
  1106 		{
       
  1107 		if(!chanPtr)
       
  1108 			{
       
  1109 			r = KErrArgument;
       
  1110 			}
       
  1111 		else
       
  1112 			{
       
  1113 			switch(chanPtr->GetChanType())
       
  1114 				{
       
  1115 				// QueueTransaction requests are only supported by channels in Master mode.
       
  1116 				case DIicBusChannel::ESlave:
       
  1117 					{
       
  1118 					r = KErrNotSupported;
       
  1119 					break;
       
  1120 					}
       
  1121 				// If the request is supported by the Master channel, send it to the channel for processing in its thread
       
  1122 				case DIicBusChannel::EMasterSlave:
       
  1123 					{
       
  1124 
       
  1125 					aTransaction->iBusId = aBusId;
       
  1126 					if(!aCallback)
       
  1127 					    r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));					    
       
  1128 					else
       
  1129 						r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
       
  1130 					break;
       
  1131 					}
       
  1132 				case DIicBusChannel::EMaster:
       
  1133 					{
       
  1134 					aTransaction->iBusId = aBusId;
       
  1135 					if(!aCallback)
       
  1136 						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
       
  1137 					else
       
  1138 						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
       
  1139 					break;
       
  1140 					}
       
  1141 				default:
       
  1142 					{
       
  1143 					r = KErrGeneral;
       
  1144 					}
       
  1145 				}
       
  1146 			}
       
  1147 		}
       
  1148 #endif
       
  1149 	return r;
       
  1150 	}
       
  1151 
       
  1152 TInt DChannelIicClient::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
       
  1153 	{
       
  1154 	TInt r = KErrNone;
       
  1155 #ifndef STANDALONE_CHANNEL
       
  1156 	r = IicBus::CancelTransaction(aBusId, aTransaction);
       
  1157 #else
       
  1158     __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
       
  1159 	if(!aTransaction)
       
  1160 		{
       
  1161 		return KErrArgument;
       
  1162 		}
       
  1163 
       
  1164 	// Get the channel
       
  1165 	TInt dumInt = 0;
       
  1166 	DIicClientChan* chanPtr = NULL;
       
  1167 	if(r == KErrNone)
       
  1168 		{
       
  1169 		r = GetChanPtr(aBusId, dumInt, chanPtr);
       
  1170 		if(r == KErrNone)
       
  1171 			{
       
  1172 			if(!chanPtr)
       
  1173 				{
       
  1174 				r = KErrArgument;
       
  1175 				}
       
  1176 			else
       
  1177 				{
       
  1178 				// QueueTransaction requests are only supported by channels in Master mode.
       
  1179 				switch(chanPtr->GetChanType())
       
  1180 					{
       
  1181 					case DIicBusChannel::ESlave:
       
  1182 						{
       
  1183 						r = KErrNotSupported;
       
  1184 						break;
       
  1185 						}
       
  1186 					case DIicBusChannel::EMasterSlave:
       
  1187 						{
       
  1188 						r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
       
  1189 						break;
       
  1190 						}
       
  1191 					case DIicBusChannel::EMaster:
       
  1192 						{
       
  1193 						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
       
  1194 						break;
       
  1195 						}
       
  1196 					default:
       
  1197 						{
       
  1198 						r = KErrGeneral;
       
  1199 						}
       
  1200 					}
       
  1201 				}
       
  1202 			}
       
  1203 		}
       
  1204 #endif
       
  1205 	return r;
       
  1206 	}
       
  1207 
       
  1208 
       
  1209 TInt DChannelIicClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
       
  1210 	{
       
  1211 	TInt r = KErrNone;
       
  1212 #ifndef STANDALONE_CHANNEL
       
  1213 	r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
       
  1214 #else
       
  1215 	// Get the channel
       
  1216 	TInt dumInt = 0;
       
  1217 	DIicClientChan* chanPtr = NULL;
       
  1218 	if(r == KErrNone)
       
  1219 		{
       
  1220 		r = GetChanPtr(aId, dumInt, chanPtr);
       
  1221 		if(r == KErrNone)
       
  1222 			{
       
  1223 			if(!chanPtr)
       
  1224 				{
       
  1225 				r = KErrArgument;
       
  1226 				}
       
  1227 			else
       
  1228 				{
       
  1229 				r = (chanPtr->GetChannelPtr())->StaticExtension(aFunction, aParam1, aParam2);
       
  1230 				}
       
  1231 			}
       
  1232 		}
       
  1233 #endif
       
  1234 	return r;
       
  1235 	}
       
  1236 
       
  1237 TInt DChannelIicClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
       
  1238 	{
       
  1239 	TInt r = KErrNone;
       
  1240 #ifndef STANDALONE_CHANNEL
       
  1241 	r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
       
  1242 #else
       
  1243 	// Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
       
  1244 	if(!aCallback || !aConfigHdr)
       
  1245 		{
       
  1246 		return KErrArgument;
       
  1247 		}
       
  1248 
       
  1249 	// Get the channel
       
  1250 	TInt chanIndex = 0;
       
  1251 	DIicClientChan* chanPtr = NULL;
       
  1252 	if(r == KErrNone)
       
  1253 		{
       
  1254 		r = GetChanPtr(aBusId, chanIndex, chanPtr);
       
  1255 		if(r == KErrNone)
       
  1256 			{
       
  1257 			if(!chanPtr)
       
  1258 				{
       
  1259 				r = KErrArgument;
       
  1260 				}
       
  1261 			else
       
  1262 				{
       
  1263 				switch(chanPtr->GetChanType())
       
  1264 					{
       
  1265 					// CaptureChannel requests are only supported by channels in Slave mode.
       
  1266 					case DIicBusChannel::EMaster:
       
  1267 						{
       
  1268 						r = KErrNotSupported;
       
  1269 						break;
       
  1270 						}
       
  1271 					case DIicBusChannel::EMasterSlave:
       
  1272 						{
       
  1273 						r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
       
  1274 						break;
       
  1275 						}
       
  1276 					case DIicBusChannel::ESlave:
       
  1277 						{
       
  1278 						r = ((DIicBusChannelSlave*)(chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
       
  1279 						break;
       
  1280 						}
       
  1281 					default:
       
  1282 						{
       
  1283 						r = KErrArgument;
       
  1284 						}
       
  1285 					}
       
  1286 				// For synchronous capture, if successful then install the channel
       
  1287 				if(r == KErrNone)
       
  1288 					{
       
  1289 					if(!aAsynch)
       
  1290 						{
       
  1291 						 iCapturedChannel.iChanPtr = chanPtr;
       
  1292 						 iCapturedChannel.iChannelId = iChannelId;
       
  1293 						}
       
  1294 					else
       
  1295 						//For asynchronous capture, record chanPtr, if later failed capture,
       
  1296 						//clean iCapturedChannel in client's callback.
       
  1297 						iCapturedChannel.iChanPtr = chanPtr;
       
  1298 					}
       
  1299 				}
       
  1300 			}
       
  1301 		}
       
  1302 #endif
       
  1303 	return r;
       
  1304 	}
       
  1305 
       
  1306 TInt DChannelIicClient::ReleaseChannel(TInt aChannelId)
       
  1307 	{
       
  1308 	TInt r = KErrNone;
       
  1309 #ifndef STANDALONE_CHANNEL
       
  1310 	r = IicBus::ReleaseChannel(aChannelId);
       
  1311 #else
       
  1312     __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
       
  1313     if(iCapturedChannel.iChannelId != aChannelId)
       
  1314             return KErrNotFound;
       
  1315 
       
  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;
       
  1323 #endif
       
  1324     return r;
       
  1325 	}
       
  1326 
       
  1327 void DChannelIicClient::DoCancel(TInt aMask)
       
  1328 	{
       
  1329 // Cancel an outstanding request.
       
  1330 	CLIENT_PRINT(("DChannelIicClient::DoCancel invoked with aMask=0x%x\n", aMask));
       
  1331 
       
  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
       
  1336 	TInt* parms[2];
       
  1337 	TInt r=Kern::ThreadRawRead(iClient,(TAny*)aMask,&(parms[0]),2*sizeof(TInt*));
       
  1338 	if(r!=KErrNone)
       
  1339 		{
       
  1340 		CLIENT_PRINT(("DChannelIicClient::DoCancel ERROR - Can't read parms[]\n"));
       
  1341 		return;	// Can't proceed if can't access request parameters
       
  1342 		}
       
  1343 	CLIENT_PRINT(("DChannelIicClient::DoCancel - TRequestStatus 0x%x, BusID = 0x%x\n",parms[0],parms[1]));
       
  1344 
       
  1345 	TTransStatusPair* searchPair = new TTransStatusPair();
       
  1346 	TTransCbPair* cbPair = new TTransCbPair();
       
  1347 	searchPair->iReq = (TRequestStatus*)(parms[0]);
       
  1348 
       
  1349 	GetWriteAccess();
       
  1350 	Lock();
       
  1351 
       
  1352 	TInt pairIndexByStatus = iTransStatArrayByStatus.FindInOrder(searchPair,TransStatusOrderByStatus);
       
  1353 	CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByStatus=0x%x\n",pairIndexByStatus));
       
  1354 	TInt pairIndexByTrans = KErrNotFound;
       
  1355 
       
  1356 	if(pairIndexByStatus<0)
       
  1357 		{
       
  1358 		// If the TRequestStatus object is not found then either the value was invalid or
       
  1359 		// the object may already have been completed.
       
  1360 		FreeWriteAccess();
       
  1361 		Unlock();
       
  1362 		CLIENT_PRINT(("DChannelIicClient::DoCancel() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndexByStatus,parms[0]));
       
  1363 		}
       
  1364 	else
       
  1365 		{
       
  1366 		// The status-transaction pair exists in the status-index array - so remove it
       
  1367 		TTransStatusPair* pairPtrStatus = iTransStatArrayByStatus[pairIndexByStatus];
       
  1368 		iTransStatArrayByStatus.Remove(pairIndexByStatus);
       
  1369 
       
  1370 		pairIndexByTrans = iTransStatArrayByTrans.FindInOrder(pairPtrStatus,TransStatusOrderByTrans);
       
  1371 		CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByTrans=0x%x\n",pairIndexByTrans));
       
  1372 		if(pairIndexByTrans>=0)
       
  1373 			{
       
  1374 			iTransStatArrayByTrans.Remove(pairIndexByTrans);
       
  1375 			}
       
  1376 		FreeWriteAccess();
       
  1377 		Unlock();
       
  1378 
       
  1379 		CLIENT_PRINT(("DChannelIicClient::DoCancel pairPtrStatus=0x%x\n", pairPtrStatus));
       
  1380 
       
  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);
       
  1390 		
       
  1391 		// Complete the TRequestStatus object according to the returned value
       
  1392 		TRequestStatus* status= (TRequestStatus*)(parms[0]);
       
  1393 		Kern::RequestComplete(iClient, status, r);
       
  1394 
       
  1395 		// Clean up
       
  1396 		delete cb;
       
  1397 		delete theCbPair;
       
  1398 		// We should call CleanupExtractTrans() to delete all the objects we created in ExtractTransData()
       
  1399 		CleanupExtractTrans(trans);
       
  1400         CleanupTransaction(trans);  
       
  1401 		delete pairPtrStatus;
       
  1402 		}
       
  1403 
       
  1404 	delete cbPair;
       
  1405 	delete searchPair;
       
  1406 
       
  1407 	return;
       
  1408 	}
       
  1409 
       
  1410 
       
  1411 // Function to support preamble testing
       
  1412 void PreambleCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
       
  1413 	{
       
  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);
       
  1421 	}
       
  1422 
       
  1423 TIicBusTransaction* DChannelIicClient::iMultiTransac;
       
  1424 
       
  1425 // Function to support multi transc testing
       
  1426 TIicBusTransaction* DChannelIicClient::MultiTranscCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
       
  1427 	{
       
  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;
       
  1436 	}
       
  1437 
       
  1438 TInt DChannelIicClient::CleanupExtractTrans(TIicBusTransaction* aTrans)
       
  1439 	{
       
  1440 	// Clean up the data created in ExtractTransData()
       
  1441 	TExtractInfo *extractInfo = new TExtractInfo();
       
  1442 	extractInfo->iTrans = aTrans;
       
  1443 	TInt index = iExtractInfoArray.FindInOrder(extractInfo, ExtractInfoOrderByTrans);
       
  1444 	if(index >= 0)
       
  1445 	    {
       
  1446 	    delete iExtractInfoArray[index];
       
  1447 	    iExtractInfoArray.Remove(index);
       
  1448 	    }
       
  1449 	delete extractInfo;
       
  1450 	return KErrNone;
       
  1451 	}
       
  1452 
       
  1453 TInt DChannelIicClient::ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans)
       
  1454 	{
       
  1455 // Utility function to create a TIicBusTransaction object from the parameters passed by the user-side TUsideTracnDesc object
       
  1456 
       
  1457 	TInt r = KErrNone;
       
  1458 	TUsideTracnDesc usTrans;
       
  1459 	r=Kern::ThreadRawRead(iClient,aUsideTrancnDesc,&usTrans,sizeof(TUsideTracnDesc));
       
  1460 	if(r!=KErrNone)
       
  1461 		{
       
  1462 		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans\n"));
       
  1463 		return KErrGeneral;	// Can't proceed if can't access request parameters
       
  1464 		}
       
  1465 	// Ensure pointers potentially used for allocation are NULL, to facilitate cleanup
       
  1466 	iSpiBuf=NULL;
       
  1467 	iI2cBuf=NULL;
       
  1468 	iTfer=NULL;
       
  1469 	iTransPreamble=NULL;
       
  1470 	iFdTfer=NULL;
       
  1471 
       
  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();
       
  1480 	TDes8* bufPtr=NULL;
       
  1481 	if(busType == ESpi)
       
  1482 		{
       
  1483 		if((spiBuf = new TConfigSpiBufV01()) == NULL)
       
  1484 			{
       
  1485 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate spiBuf\n"));
       
  1486 			return KErrNoMemory;
       
  1487 			}
       
  1488 		if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
       
  1489 			{
       
  1490 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to spiBuf\n"));
       
  1491 			return KErrGeneral;
       
  1492 			}
       
  1493 		bufPtr=(TDes8*)spiBuf;
       
  1494 		}
       
  1495 	else if(busType == EI2c)
       
  1496 		{
       
  1497 		if((i2cBuf = new TConfigI2cBufV01()) == NULL)
       
  1498 			{
       
  1499 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate i2cBuf\n"));
       
  1500 			return KErrNoMemory;
       
  1501 			}
       
  1502 		if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *i2cBuf, 0, KChunkShiftBy0 ))!=KErrNone)
       
  1503 			{
       
  1504 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to i2cBuf\n"));
       
  1505 			return KErrGeneral;
       
  1506 			}
       
  1507 		bufPtr=(TDes8*)i2cBuf;
       
  1508 		}
       
  1509 	else
       
  1510 		{
       
  1511 		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unrecognised bus type\n"));
       
  1512 		return KErrGeneral;
       
  1513 		}
       
  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));
       
  1519 	if(r!=KErrNone)
       
  1520 		{
       
  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
       
  1523 		}
       
  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);
       
  1527 	if(r!=KErrNone)
       
  1528 		{
       
  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
       
  1531 		}
       
  1532 
       
  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;
       
  1538 
       
  1539 	if((transFlags&KTransactionWithPreamble)&&(transFlags&KTransactionWithMultiTransc))
       
  1540 		{
       
  1541 		if(usTrans.iPreambleArg == NULL)
       
  1542 			{
       
  1543 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
       
  1544 			return KErrArgument;
       
  1545 			}
       
  1546 		if(usTrans.iMultiTranscArg == NULL)
       
  1547 			{
       
  1548 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
       
  1549 			return KErrArgument;
       
  1550 			}
       
  1551 		iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
       
  1552 		iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
       
  1553 		TIicBusTransactionPreambleExt* transExt;
       
  1554 
       
  1555 		transExt = new TIicBusTransactionPreambleExt(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this,
       
  1556 							(TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
       
  1557 		if(transExt == NULL)
       
  1558 			{
       
  1559 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
       
  1560 			return KErrNoMemory;	// Can't proceed if can't access request parameters
       
  1561 			}
       
  1562 		aTrans = transExt;
       
  1563 
       
  1564 		}
       
  1565 	else if(transFlags & KTransactionWithPreamble)
       
  1566 		{
       
  1567 		// Preamble required - construct the derived-class transaction object
       
  1568 		if(usTrans.iPreambleArg == NULL)
       
  1569 			{
       
  1570 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - preamble TRequestStatus==NULL\n"));
       
  1571 			return KErrArgument;
       
  1572 			}
       
  1573 		iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
       
  1574 		TIicBusTransactionPreamble* TransPreamble;
       
  1575 		TransPreamble = new TIicBusTransactionPreamble(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this);
       
  1576 		if(TransPreamble == NULL)
       
  1577 			{
       
  1578 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
       
  1579 			return KErrNoMemory;	// Can't proceed if can't access request parameters
       
  1580 			}
       
  1581 		aTrans = TransPreamble;
       
  1582 		}
       
  1583 	else if(transFlags & KTransactionWithMultiTransc)
       
  1584 		{
       
  1585 		// Preamble required - construct the derived-class transaction object
       
  1586 		if(usTrans.iMultiTranscArg == NULL)
       
  1587 			{
       
  1588 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Multi Transc TRequestStatus==NULL\n"));
       
  1589 			return KErrArgument;
       
  1590 			}
       
  1591 		iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
       
  1592 		TIicBusTransactionMultiTransc* transMultiTransc;
       
  1593 		transMultiTransc = new TIicBusTransactionMultiTransc(bufPtr, tfer7, (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
       
  1594 		if(transMultiTransc == NULL)
       
  1595 			{
       
  1596 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
       
  1597 			return KErrNoMemory;	// Can't proceed if can't access request parameters
       
  1598 			}
       
  1599 		aTrans = transMultiTransc;
       
  1600 		}
       
  1601 	else
       
  1602 		{
       
  1603 		// Preamble not required
       
  1604 		aTrans = new TIicBusTransaction(bufPtr, tfer7);
       
  1605 		if(aTrans == NULL)
       
  1606 			{
       
  1607 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
       
  1608 			return KErrNoMemory;	// Can't proceed if can't access request parameters
       
  1609 			}
       
  1610 		}
       
  1611 
       
  1612 	// If full duplex transaction is required get that information, too
       
  1613 	usTferPtr = usTrans.iFullDuplexTrans;
       
  1614 	if(usTferPtr!=NULL)
       
  1615 		{
       
  1616 		r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
       
  1617 		if(r!=KErrNone)
       
  1618 			{
       
  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
       
  1621 			}
       
  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);
       
  1625 		if(r!=KErrNone)
       
  1626 			{
       
  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
       
  1629 			}
       
  1630 
       
  1631 		type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
       
  1632 		r=aTrans->SetFullDuplexTrans(iFdTfer);
       
  1633 		if(r!=KErrNone)
       
  1634 			{
       
  1635 			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - SetFullDuplexTrans returned %d\n",r));
       
  1636 			return r;
       
  1637 			}
       
  1638 		}
       
  1639 	extractInfo->iTrans = aTrans;
       
  1640 	iExtractInfoArray.InsertInOrder(extractInfo, ExtractInfoOrderByTrans);
       
  1641 	return r;
       
  1642 	}
       
  1643 
       
  1644 #define KMaxTferTextLength 20
       
  1645 #define KLongNodeTestLength 15
       
  1646 #define KShortNodeTestLength 5
       
  1647 _LIT(KFullTracnHdrText,"Full duplex test");		// length = 22
       
  1648 #define KFullTracnHdrTextLength 16
       
  1649 
       
  1650 
       
  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)
       
  1660 	{
       
  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);
       
  1667 
       
  1668 	if(buf1 == NULL||buf2 == NULL||buf3 == NULL||
       
  1669 		tfer1 == NULL||tfer2 == NULL||tfer3 == NULL)
       
  1670 		{
       
  1671 		delete buf1; delete buf2; delete buf3;
       
  1672 		delete tfer1; delete tfer2;	delete tfer3;
       
  1673 		return KErrNoMemory;
       
  1674 		}
       
  1675 
       
  1676 	TInt i;
       
  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('*');
       
  1680 
       
  1681 	tfer1->LinkAfter(tfer2);
       
  1682 
       
  1683 	//allow two nodes
       
  1684 	if(aNodeLength3>0)
       
  1685 		{
       
  1686 		tfer2->LinkAfter(tfer3);
       
  1687 		}
       
  1688 
       
  1689 	return KErrNone;
       
  1690 
       
  1691 	}
       
  1692 
       
  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)
       
  1702 	{
       
  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);
       
  1709 
       
  1710 	if(buf4 == NULL||buf5 == NULL||buf6 == NULL||
       
  1711 		tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
       
  1712 		{
       
  1713 		delete buf4; delete buf5; delete buf6;
       
  1714 		delete tfer4; delete tfer5;	delete tfer6;
       
  1715 		return KErrNoMemory;
       
  1716 		}
       
  1717 
       
  1718 	TInt i;
       
  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('*');
       
  1722 
       
  1723 	tfer4->LinkAfter(tfer5);
       
  1724 
       
  1725 	//allow two nodes
       
  1726 	if(aNodeLength3>0)
       
  1727 		{
       
  1728 		tfer5->LinkAfter(tfer6);
       
  1729 		}
       
  1730 
       
  1731 	return KErrNone;
       
  1732 
       
  1733 	}
       
  1734 
       
  1735 // Delete transaction and all allocated transfers and buffers
       
  1736 TInt DChannelIicClient::DeleteFullDuplexTest(TIicBusTransaction *aTrans)
       
  1737 	{
       
  1738 	delete buf1; delete buf2; delete buf3;
       
  1739 	delete tfer1; delete tfer2; delete tfer3;
       
  1740 
       
  1741 	delete buf4; delete buf5; delete buf6;
       
  1742 	delete tfer4; delete tfer5; delete tfer6;
       
  1743 
       
  1744 	delete header;
       
  1745 	delete aTrans;
       
  1746 
       
  1747 	return KErrNone;
       
  1748 	}
       
  1749 
       
  1750 // Do full duplex creation test
       
  1751 TInt DChannelIicClient::DoCreateFullDuplexTransTest(TInt aTestType)
       
  1752 	{
       
  1753 	CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest starts\n"));
       
  1754 
       
  1755 	TInt r=KErrNone;
       
  1756 	switch(aTestType)
       
  1757 		{
       
  1758 		case RBusDevIicClient::ETestValidFullDuplexTrans:
       
  1759 			{
       
  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;
       
  1771 			break;
       
  1772 			}
       
  1773 		case RBusDevIicClient::ETestInvalidFullDuplexTrans1:
       
  1774 			{
       
  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;
       
  1786 			break;
       
  1787 			}
       
  1788 		case RBusDevIicClient::ETestInvalidFullDuplexTrans2:
       
  1789 			{
       
  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;
       
  1801 			break;
       
  1802 			}
       
  1803 		case RBusDevIicClient::ETestLastNodeFullDuplexTrans:
       
  1804 			{
       
  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;
       
  1816 			break;
       
  1817 			}
       
  1818 		case RBusDevIicClient::ETestDiffNodeNoFullDuplexTrans:
       
  1819 			{
       
  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;
       
  1831 			break;
       
  1832 			}
       
  1833 
       
  1834 
       
  1835 		default:
       
  1836 			break;
       
  1837 		}
       
  1838 
       
  1839 	header = HBuf8::New(KFullTracnHdrTextLength);
       
  1840 	TIicBusTransaction *Trans = new TIicBusTransaction(header,tfer1);
       
  1841 
       
  1842 	if((r!=KErrNone) || (header == NULL) || (Trans == NULL))
       
  1843 		{
       
  1844 		CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest ERROR - failed to allocate the necessary memory\n"));
       
  1845 		DeleteFullDuplexTest(Trans);
       
  1846 		return KErrNoMemory;
       
  1847 		}
       
  1848 
       
  1849 	header->Copy(KFullTracnHdrText);
       
  1850 
       
  1851 	TInt TestResult = Trans->SetFullDuplexTrans(tfer4);
       
  1852 
       
  1853 	CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest IIC after SetFullDuplexTrans TestResult =%d\n", TestResult));
       
  1854 
       
  1855 	r = DeleteFullDuplexTest(Trans);
       
  1856 
       
  1857 	return TestResult;
       
  1858 
       
  1859 	}
       
  1860 
       
  1861 
       
  1862 TInt DChannelIicClient::CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf)
       
  1863 // Utility function to create a buffer for the SPI bus
       
  1864 	{
       
  1865 	TInt r=CreateSpiBuf(aBuf, ESpiWordWidth_8, 100000, ESpiPolarityLowRisingEdge, 100 ,ELittleEndian, EMsbFirst, 10, ESpiCSPinActiveLow);
       
  1866 	return r;
       
  1867 	}
       
  1868 
       
  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)
       
  1882 	{
       
  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;
       
  1887 	TInt r = KErrNone;
       
  1888 
       
  1889 	r = StaticExtension(aBusId, testId, NULL, NULL);
       
  1890 	__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
       
  1891 	if(r == KErrNone)
       
  1892 		{
       
  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);
       
  1900 
       
  1901 		if(buf1 == NULL||buf2 == NULL||buf3 == NULL||buf4 == NULL||buf5 == NULL||buf6 == NULL)
       
  1902 			{
       
  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;
       
  1906 			}
       
  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);
       
  1914 
       
  1915 		if(tfer1 == NULL||tfer2 == NULL||tfer3 == NULL||tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
       
  1916 			{
       
  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;
       
  1921 			}
       
  1922 
       
  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
       
  1929 
       
  1930 
       
  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);
       
  1938 
       
  1939 		if(r != KErrNone||spiHeader1 == NULL||spiHeader2 == NULL||spiHeader3 == NULL||spiHeader4 == NULL||spiHeader5 == NULL||spiHeaderBlock == NULL)
       
  1940 			{
       
  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;
       
  1946 			}
       
  1947 
       
  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]);
       
  1955 
       
  1956 		if(Transc1 == NULL||Transc2 == NULL||Transc3 == NULL||Transc4 == NULL||Transc5 == NULL||TranscBlock == NULL)
       
  1957 			{
       
  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;
       
  1964 			}
       
  1965 
       
  1966 		//dummy call back func is provided for asyn call
       
  1967 		TIicBusCallback* cb = new TIicBusCallback(DummyCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
       
  1968 
       
  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__));
       
  1974 
       
  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__));
       
  1978 
       
  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__));
       
  1989 
       
  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__));
       
  1994 
       
  1995 		#define KPriorityTestGetResultRetry 3
       
  1996 		for(TInt i=0; i<KPriorityTestGetResultRetry ; i++)
       
  1997 			{
       
  1998 			NKern::Sleep(500);
       
  1999 			testId=((TUint)RBusDevIicClient::EGetTestResult)<<1;
       
  2000 			TestResult = StaticExtension(aBusId, testId, NULL, NULL);
       
  2001 			if(TestResult!=KErrNotReady) break;
       
  2002 			}
       
  2003 
       
  2004 		cb->Cancel();
       
  2005 		delete cb;
       
  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;
       
  2010 
       
  2011 		}
       
  2012 	r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
       
  2013 	return TestResult;
       
  2014 	}
       
  2015 
       
  2016 TInt DChannelIicClient::ConstructTransactionOne(TIicBusTransaction*& aTrans)
       
  2017 	{
       
  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))
       
  2028 		{
       
  2029 		CLIENT_PRINT(("DChannelIicClient::ConstructTransactionOne ERROR - failed to allocate the necessary memory\n"));
       
  2030 		delete buf1;
       
  2031 		delete buf2;
       
  2032 		delete buf3;
       
  2033 		delete tfer1;
       
  2034 		delete tfer2;
       
  2035 		delete tfer3;
       
  2036 		delete spiHeader;
       
  2037 		delete aTrans;
       
  2038 		return KErrNoMemory;
       
  2039 		}
       
  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);
       
  2046 	return KErrNone;
       
  2047 	}
       
  2048 
       
  2049 void DChannelIicClient::CleanupTransactionOne(TIicBusTransaction*& aTrans)
       
  2050 	{
       
  2051 	// Release the allocated memory
       
  2052 	delete buf1;
       
  2053 	buf1=NULL;
       
  2054 	delete buf2;
       
  2055 	buf2=NULL;
       
  2056 	delete buf3;
       
  2057 	buf3=NULL;
       
  2058 	delete tfer1;
       
  2059 	tfer1=NULL;
       
  2060 	delete tfer2;
       
  2061 	tfer2=NULL;
       
  2062 	delete tfer3;
       
  2063 	tfer3=NULL;
       
  2064 	delete spiHeader;
       
  2065 	spiHeader=NULL;
       
  2066 	delete aTrans;
       
  2067 	aTrans=NULL;
       
  2068 	}
       
  2069 
       
  2070 
       
  2071 void DChannelIicClient::CleanupTransaction(TIicBusTransaction*& aTrans)
       
  2072 	{
       
  2073 	delete iSpiBuf;
       
  2074 	iSpiBuf=NULL;
       
  2075 	delete iI2cBuf;
       
  2076 	iI2cBuf=NULL;
       
  2077 	TIicBusTransfer* currTfer = iTfer;
       
  2078 	TIicBusTransfer* nextTfer = NULL;
       
  2079 	while(currTfer)
       
  2080 		{
       
  2081 		TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
       
  2082 		delete currTfer;
       
  2083 		if(nextTfer)
       
  2084 			currTfer = nextTfer;
       
  2085 		else
       
  2086 			currTfer = NULL;
       
  2087 		};
       
  2088 	iTfer=NULL;
       
  2089 	currTfer = iFdTfer;
       
  2090 	nextTfer = NULL;
       
  2091 	while(currTfer)
       
  2092 		{
       
  2093 		TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
       
  2094 		delete currTfer;
       
  2095 		if(nextTfer)
       
  2096 			currTfer = nextTfer;
       
  2097 		else
       
  2098 			currTfer = NULL;
       
  2099 		};
       
  2100 	iFdTfer=NULL;
       
  2101 	if(aTrans!=NULL)
       
  2102 		{
       
  2103 		delete aTrans;
       
  2104 		aTrans=NULL;
       
  2105 		}
       
  2106 	if(iTransPreamble!=NULL)
       
  2107 		{
       
  2108 		delete iTransPreamble;
       
  2109 		iTransPreamble=NULL;
       
  2110 		}
       
  2111 	}
       
  2112 
       
  2113 void DChannelIicClient::TransModifCallback(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt aResult, TAny* aParam)
       
  2114 	{
       
  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);
       
  2119 
       
  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);
       
  2122 
       
  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);
       
  2127 	return;
       
  2128 	}
       
  2129 
       
  2130 
       
  2131 void DChannelIicClient::TestTransModification(TIicBusTransaction* aTransaction,
       
  2132 											  TIicBusTransfer* aHdTfer,
       
  2133 											  TIicBusTransfer* aFdTfer,
       
  2134 											  TDes8* aHdr)
       
  2135 	{
       
  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.
       
  2143 	//
       
  2144 	TDes8* origBuf = NULL;
       
  2145 	TInt8 origGranularity = 0;
       
  2146 
       
  2147 	// Create a buffer for use in this function
       
  2148 	_LIT(temporaryText,"Temporary Text");
       
  2149 	TBuf8<15> tempBuf_8;
       
  2150 	tempBuf_8.Copy(temporaryText);
       
  2151 
       
  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);
       
  2157 
       
  2158 	origBuf = (TDes8*)(aFdTfer->GetBuffer());
       
  2159 	origGranularity = aFdTfer->WordWidth();
       
  2160 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
       
  2161 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
       
  2162 
       
  2163 	// Test transfers can be removed from the transaction
       
  2164 	aTransaction->RemoveHalfDuplexTrans();
       
  2165 	aTransaction->RemoveFullDuplexTrans();
       
  2166 
       
  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);
       
  2172 
       
  2173 	origBuf = (TDes8*)(aFdTfer->GetBuffer());
       
  2174 	origGranularity = aFdTfer->WordWidth();
       
  2175 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
       
  2176 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
       
  2177 
       
  2178 	// Test transfers can be re-added to the transaction
       
  2179 	aTransaction->SetHalfDuplexTrans(aHdr,aHdTfer);
       
  2180 	aTransaction->SetFullDuplexTrans(aFdTfer);
       
  2181 
       
  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);
       
  2187 
       
  2188 	origBuf = (TDes8*)(aFdTfer->GetBuffer());
       
  2189 	origGranularity = aFdTfer->WordWidth();
       
  2190 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
       
  2191 	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
       
  2192 
       
  2193 	return;
       
  2194 	}
       
  2195 
       
  2196 TInt DChannelIicClient::DoControl(TInt aId, TAny* a1, TAny* a2)
       
  2197 	{
       
  2198 	CLIENT_PRINT(("DChannelIicClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
       
  2199 	TInt r=KErrNone;
       
  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
       
  2202 	TInt ctrlIoVal = 0;
       
  2203 	if((aId & KTestMasterControlIo) == KTestMasterControlIo)
       
  2204 		ctrlIoVal = (aId << 1);
       
  2205 	if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
       
  2206 		ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
       
  2207 	switch(aId)
       
  2208 		{
       
  2209 		case(RBusDevIicClient::EQTransSync):
       
  2210 			{
       
  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;
       
  2216 			
       
  2217 			//Read the transaction header to determin if it is a multi-transaction type
       
  2218 			TUsideTracnDesc usTrans;
       
  2219 
       
  2220 			if((Kern::ThreadRawRead(iClient,a2,&usTrans,sizeof(TUsideTracnDesc)))!=KErrNone)
       
  2221 				{
       
  2222 				CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
       
  2223 				return KErrGeneral;
       
  2224 				}
       
  2225 
       
  2226 			if((usTrans.iFlags)&KTransactionWithMultiTransc)
       
  2227 				{
       
  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;}
       
  2241 
       
  2242 
       
  2243 				if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
       
  2244 					{
       
  2245 					CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
       
  2246 					return KErrGeneral;
       
  2247 					}
       
  2248 
       
  2249 				tfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
       
  2250 				if(tfer == NULL) {delete buf1; delete spiBuf; return KErrNoMemory;}
       
  2251 
       
  2252 				iMultiTransac = new TIicBusTransaction((TDes8*)spiBuf, tfer);
       
  2253 				if(iMultiTransac == NULL) {delete buf1; delete spiBuf; delete tfer; return KErrNoMemory;}
       
  2254 				}
       
  2255 			r = ExtractTransData((TUsideTracnDesc*)a2, trans);
       
  2256 			if(r!=KErrNone)
       
  2257 				{
       
  2258 				CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - ExtractTransData returned %d\n",r));
       
  2259 				return r;
       
  2260 				}
       
  2261 			CLIENT_PRINT(("DChannelIicClient::DoControl invoking (synchronous) QueueTransaction with busId=0x%x, trans=0x%x\n",(TUint32)a1,trans));
       
  2262 
       
  2263 			r = QueueTransaction((TUint32)a1, trans);
       
  2264 			CleanupExtractTrans(trans);
       
  2265 			CleanupTransaction(trans);
       
  2266 			if((usTrans.iFlags)&KTransactionWithMultiTransc)
       
  2267 				{
       
  2268 				delete buf1;
       
  2269 				delete spiBuf;
       
  2270 				delete tfer;
       
  2271 				delete iMultiTransac;
       
  2272 				}
       
  2273 			break;
       
  2274 			}
       
  2275 		case(RBusDevIicClient::ECtlIoBlockReqCompletion):
       
  2276 		case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
       
  2277 		case(RBusDevIicClient::ECtlIoDeRegChan):
       
  2278 			{
       
  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);
       
  2283 			break;
       
  2284 			}
       
  2285 		case(RBusDevIicClient::ECtlIoTestFullDuplexTrans):
       
  2286 			{
       
  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);
       
  2290 			break;
       
  2291 			}
       
  2292 		case(RBusDevIicClient::ECtlIoPriorityTest):
       
  2293 			{
       
  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);
       
  2297 			break;
       
  2298 			}
       
  2299 
       
  2300 		case(RBusDevIicClient::ECtlIoTracnOne):
       
  2301 			{
       
  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__));
       
  2307 			if(r == KErrNone)
       
  2308 				{
       
  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);
       
  2315 				}
       
  2316 			r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
       
  2317 			break;
       
  2318 			}
       
  2319 		case(RBusDevIicClient::ECtlIoSetTimeOutFlag):
       
  2320 			{
       
  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);
       
  2325 			break;
       
  2326 			}
       
  2327 		case(RBusDevIicClient::ECtlIoNone):
       
  2328 			{
       
  2329 			CLIENT_PRINT(("DChannelIicClient::DoControl Return the bus to its default test state"));
       
  2330 			r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
       
  2331 			break;
       
  2332 			}
       
  2333 
       
  2334 // Support for MasterSlave processing
       
  2335 
       
  2336 		case(RBusDevIicClient::ECaptureChanSync):
       
  2337 			{
       
  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;
       
  2342 			//
       
  2343 			TInt* parms[2];
       
  2344 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
       
  2345 			if(r!=KErrNone)
       
  2346 				break;	// Can't proceed if can't access request parameters
       
  2347 			//
       
  2348 		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
       
  2349 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
       
  2350   			if (hdrSize<=0)
       
  2351 				{
       
  2352 				CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
       
  2353  				return KErrArgument;
       
  2354 				}
       
  2355 			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
       
  2356 				return KErrNoMemory;
       
  2357 			r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
       
  2358 			if(r!=KErrNone)
       
  2359 				{
       
  2360 				delete iConfigHdr;
       
  2361 				return r;
       
  2362 				}
       
  2363 			// Store the address of the user-side variable to update with the ChannelId
       
  2364 			iClientChanId=parms[1];
       
  2365 
       
  2366 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
       
  2367 			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
       
  2368 			if(r != KErrNone)
       
  2369 			    delete iConfigHdr;
       
  2370 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
       
  2371 
       
  2372 			TInt r=Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
       
  2373 			(void)r;	// Silence the compiler
       
  2374 
       
  2375 			break;
       
  2376 			}
       
  2377 
       
  2378 		case(RBusDevIicClient::EReleaseChan):
       
  2379 			{
       
  2380 			// a1 represents TInt aChannelId
       
  2381 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
       
  2382 			r = ReleaseChannel((TInt)a1);
       
  2383 			delete iConfigHdr;
       
  2384 			break;
       
  2385 			}
       
  2386 
       
  2387 		case(RBusDevIicClient::EInitSlaveClient):
       
  2388 			{
       
  2389 			r=InitSlaveClient();
       
  2390 			break;
       
  2391 			}
       
  2392 		
       
  2393 #ifdef STANDALONE_CHANNEL		
       
  2394         case(RBusDevIicClient::ETestIicChannelInlineFunc):
       
  2395             {  
       
  2396             TTestIicChannelInterface channelInterface(DIicBusChannel::EMaster, DIicBusChannel::EI2c, DIicBusChannel::EHalfDuplex);
       
  2397             r = channelInterface.TestInterface();
       
  2398             break;         
       
  2399             }
       
  2400 #endif
       
  2401         
       
  2402         default:
       
  2403 			{
       
  2404 			CLIENT_PRINT(("DChannelIicClient::DoControl - unrecognised value for aId=0x%x\n",aId));
       
  2405 			r=KErrArgument;
       
  2406 			break;
       
  2407 			}
       
  2408 		}
       
  2409 	return r;
       
  2410 	}
       
  2411 
       
  2412 TInt DChannelIicClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
  2413 	{
       
  2414 	CLIENT_PRINT(("DChannelIicClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
       
  2415 
       
  2416 	TInt r=KErrNone;
       
  2417 	switch(aId)
       
  2418 		{
       
  2419 		case(RBusDevIicClient::EQTransAsync):
       
  2420 			{
       
  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);
       
  2425 			if(r!=KErrNone)
       
  2426 				{
       
  2427 				CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - ExtractTransData returned %d\n",r));
       
  2428 				return r;
       
  2429 				}
       
  2430 			// Create TIicBusCallback object
       
  2431 			TIicBusCallback* cb = new TIicBusCallback(AsyncCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
       
  2432 			TTransCbPair* cbPair = new TTransCbPair();
       
  2433 			cbPair->iCb=cb;
       
  2434 			cbPair->iTrans=trans;
       
  2435 			// Create an entry in the RPointerArray for TRequestStatus - TIicBusTransaction pairs
       
  2436 			TTransStatusPair* pair = new TTransStatusPair();
       
  2437 			pair->iReq=aStatus;
       
  2438 			pair->iTrans=trans;
       
  2439 			r=InsertPairs(pair,cbPair);
       
  2440 			if(r!=KErrNone)
       
  2441 				{
       
  2442 				CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - InsertInOrder returned %d\n",r));
       
  2443 				return r;
       
  2444 				}
       
  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);
       
  2447 			if(r!=KErrNone)
       
  2448 				{
       
  2449 				// The transaction was not queued - since it will not be completed asynchronously, need to remove it here
       
  2450 				GetWriteAccess();
       
  2451 				Lock();
       
  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);
       
  2461 				FreeWriteAccess();
       
  2462 				Unlock();
       
  2463 				Kern::RequestComplete(iClient, aStatus, r);
       
  2464 				delete cb;
       
  2465 				delete cbPair;
       
  2466 				CleanupExtractTrans(pair->iTrans);
       
  2467 				CleanupTransaction(pair->iTrans);			
       
  2468 				delete pair;
       
  2469 				}
       
  2470 			break;
       
  2471 			}
       
  2472 
       
  2473 		case(RBusDevIicClient::ECtrlIoTestBufReUse):
       
  2474 			{
       
  2475 			iStatus = aStatus;
       
  2476 			// a1 specifies Bus Realisation Config to use
       
  2477 
       
  2478 			// Ensure object pointers are made available
       
  2479 			CleanupTransaction(iTrans);
       
  2480 
       
  2481 			TInt r = KErrNone;
       
  2482 			TIicBusCallback* cb = NULL;
       
  2483 
       
  2484 			// Use default constructor to create an empty transaction
       
  2485 			iTrans = new TIicBusTransaction();
       
  2486 			if(iTrans == NULL)
       
  2487 				{
       
  2488 				CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTrans=NULL\n"));
       
  2489 				r = KErrNoMemory;
       
  2490 				}
       
  2491 
       
  2492 			// Create a header for the transaction
       
  2493 			if(r == KErrNone)
       
  2494 				{
       
  2495 				r = CreateDefaultSpiBuf(iSpiBuf);
       
  2496 				if(r != KErrNone)
       
  2497 					{
       
  2498 					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - CreateDefaultSpiBuf returned %d\n",r));
       
  2499 					}
       
  2500 				}
       
  2501 
       
  2502 			// Create and add transfer lists for half-duplex and full-duplex entries in the transaction
       
  2503 			if(r == KErrNone)
       
  2504 				{
       
  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);
       
  2510 				if(iTfer == NULL)
       
  2511 					{
       
  2512 					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTfer=NULL\n"));
       
  2513 					r = KErrNoMemory;
       
  2514 					}
       
  2515 				else
       
  2516 					{
       
  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)
       
  2522 						{
       
  2523 						CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempHdTfer=NULL\n"));
       
  2524 						r = KErrNoMemory;
       
  2525 						}
       
  2526 					else
       
  2527 						{
       
  2528 						iTfer->LinkAfter(tempHdTfer);
       
  2529 						}
       
  2530 					}
       
  2531 				if(r == KErrNone)
       
  2532 					{
       
  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);
       
  2537 					if(iFdTfer == NULL)
       
  2538 						{
       
  2539 						CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iFdTfer=NULL\n"));
       
  2540 						r = KErrNoMemory;
       
  2541 						}
       
  2542 					else
       
  2543 						{
       
  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)
       
  2549 							{
       
  2550 							CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempFdTfer=NULL\n"));
       
  2551 							r = KErrNoMemory;
       
  2552 							}
       
  2553 						else
       
  2554 							{
       
  2555 							iFdTfer->LinkAfter(tempFdTfer);
       
  2556 							}
       
  2557 						}
       
  2558 					}
       
  2559 				}
       
  2560 
       
  2561 			// Add the Header and Transfers to the Transaction
       
  2562 			if(r == KErrNone)
       
  2563 				r = iTrans->SetHalfDuplexTrans(iSpiBuf, iTfer);
       
  2564 				if(r != KErrNone)
       
  2565 					{
       
  2566 					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetHalfDuplexTrans returned %d\n",r));
       
  2567 					}
       
  2568 
       
  2569 			if(r == KErrNone)
       
  2570 				r = iTrans->SetFullDuplexTrans(iFdTfer);
       
  2571 				if(r != KErrNone)
       
  2572 					{
       
  2573 					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetFullDuplexTrans returned %d\n",r));
       
  2574 					}
       
  2575 
       
  2576 			// Specify the callback object to use
       
  2577 			if(r == KErrNone)
       
  2578 				{
       
  2579 				cb = new TIicBusCallback(TransModifCallback, this, iDfcQue, 5); // 5 arbitrary
       
  2580 				if(cb == NULL)
       
  2581 					{
       
  2582 					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - cb=NULL\n"));
       
  2583 					r = KErrNoMemory;
       
  2584 					}
       
  2585 				}
       
  2586 
       
  2587 			// Since the transaction is not yet queued, should be able to modify the transfer and transaction content
       
  2588 			TestTransModification(iTrans, iTfer, iFdTfer, iSpiBuf);
       
  2589 
       
  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;
       
  2596 
       
  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);
       
  2601 			if(r != KErrNone)
       
  2602 				{
       
  2603 				Kern::RequestComplete(iClient, iStatus, r);
       
  2604 				delete iTransBufReuseData.iCallback;	// Must do this before deleting the Transaction in CleanupTransaction
       
  2605 				CleanupTransaction(iTrans);
       
  2606 				}
       
  2607 			break;
       
  2608 			}
       
  2609 		default:
       
  2610 			{
       
  2611 			CLIENT_PRINT(("DChannelIicClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
       
  2612 			r=KErrArgument;
       
  2613 			break;
       
  2614 			}
       
  2615 		}
       
  2616 	return r;
       
  2617 	}
       
  2618 
       
  2619 
       
  2620 // Support for MasterSlave processing
       
  2621 static void MsSlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam)
       
  2622 	{
       
  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)
       
  2629 		{
       
  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));
       
  2634 		if(r == KErrNone)
       
  2635 			r=aReturn;
       
  2636 	    channel->RequestComplete(r);	// Inform user of error
       
  2637 		return;
       
  2638 		}
       
  2639 	else
       
  2640 		{
       
  2641 		CLIENT_PRINT(("\nMsSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
       
  2642 		channel->RequestComplete(aReturn);	// Inform user of error
       
  2643 		}
       
  2644 	}
       
  2645 
       
  2646 void DChannelIicClient::RequestComplete(TInt r)
       
  2647 	{
       
  2648 	Kern::RequestComplete(iClient, iStatus, r);
       
  2649 	}
       
  2650 
       
  2651 
       
  2652 TInt DChannelIicClient::InitSlaveClient()
       
  2653 	{
       
  2654 	iNotif = new TIicBusSlaveCallback(MsSlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
       
  2655 	if(iNotif == NULL)
       
  2656 		{
       
  2657 		CLIENT_PRINT(("> DChannelIicClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
       
  2658 		return KErrNoMemory;
       
  2659 		}
       
  2660 	return KErrNone;
       
  2661 	}
       
  2662