kerneltest/e32test/iic/iic_psl/iic_slaveclient.cpp
changeset 0 a41df078684a
child 90 947f0dc9f7a8
child 256 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_slaveclient.cpp
       
    15 // Simulated client of IIC Platform Independent Layer (PIL) Slave functionality
       
    16 //
       
    17 
       
    18 #include <kernel/kern_priv.h>		// for DThread, TDfc
       
    19 #ifdef STANDALONE_CHANNEL
       
    20 #include <drivers/iic_transaction.h>
       
    21 #else
       
    22 #include <drivers/iic.h>
       
    23 #endif
       
    24 #include "../t_iic.h"
       
    25 
       
    26 #ifdef STANDALONE_CHANNEL
       
    27 #include <drivers/iic_channel.h>
       
    28 #include "i2c.h"
       
    29 #endif
       
    30 #ifdef LOG_SLAVECLIENT
       
    31 #define CLIENT_PRINT(str) Kern::Printf str
       
    32 #else
       
    33 #define CLIENT_PRINT(str)
       
    34 #endif
       
    35 
       
    36 //For channel creation
       
    37 #ifdef STANDALONE_CHANNEL
       
    38 #define NUM_CHANNELS 3 // Arbitrary
       
    39 
       
    40 #if defined(MASTER_MODE) && !defined(SLAVE_MODE)
       
    41 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
       
    42 #elif defined(MASTER_MODE) && defined(SLAVE_MODE)
       
    43 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
       
    44 #else
       
    45 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
       
    46 #endif
       
    47 #define CHANNEL_TYPE(n) (KChannelTypeArray[n])
       
    48 #define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex)
       
    49 #define BUS_TYPE (DIicBusChannel::EI2c)
       
    50 
       
    51 #if defined(MASTER_MODE)
       
    52 const TInt8 KI2cChannelNumBase = 10;	// Arbitrary, real platform may consult the Configuration Repository
       
    53 										// Note limit of 5 bit representation (0-31)
       
    54 
       
    55 #else
       
    56 const TInt8 KI2cChannelNumBase = 10 + NUM_CHANNELS;	// For Slave mode, want to provide different response
       
    57 													// If client assumes Master mode, should be informed not available
       
    58 #endif/*MASTER_MODE*/
       
    59 
       
    60 LOCAL_C TInt8 AssignChanNumI2c()
       
    61 	{
       
    62 	static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
       
    63 	CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
       
    64 	return iBaseChanNumI2c++; // Arbitrary, for illustration
       
    65 	}
       
    66 
       
    67 class DIicSlaveClientChan : public DBase
       
    68 	{
       
    69 public:
       
    70 	DIicSlaveClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TInt aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
       
    71 	~DIicSlaveClientChan();
       
    72 	TInt GetChanNum()const {return iChanNumber;};
       
    73 	TInt GetChanType()const {return iChanType;};
       
    74 	DIicBusChannel* GetChannelPtr(){return iChan;};
       
    75 private:
       
    76 	TInt8 iChanNumber;
       
    77 	TInt iChanType;
       
    78 	DIicBusChannel* iChan;
       
    79 	};
       
    80 
       
    81 DIicSlaveClientChan::~DIicSlaveClientChan()
       
    82 	{
       
    83 	if(iChan)
       
    84 		delete iChan;
       
    85 	}
       
    86 
       
    87 #endif/*STANDALONE_CHANNEL*/
       
    88 
       
    89 const TInt KIicSlaveClientThreadPriority = 24;
       
    90 
       
    91 const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest
       
    92 
       
    93 const TInt KMaxNumChannels = 2;	// 1 "true" slave, one "dummy"
       
    94 
       
    95 #ifdef STANDALONE_CHANNEL
       
    96 _LIT(KLddRootName,"iic_slaveclient_ctrless");
       
    97 #else
       
    98 _LIT(KLddRootName,"iic_slaveclient");
       
    99 #endif
       
   100 _LIT(KIicSlaveClientThreadName,"IicSlaveClientLddThread");
       
   101 
       
   102 
       
   103 struct TCapsIicSlaveClient
       
   104     {
       
   105     TVersion version;
       
   106     };
       
   107 
       
   108 
       
   109 class DDeviceIicSlaveClient : public DLogicalDevice
       
   110     {
       
   111     public:
       
   112     /**
       
   113      * The constructor
       
   114      */
       
   115     DDeviceIicSlaveClient();
       
   116     /**
       
   117      * The destructor
       
   118      */
       
   119     ~DDeviceIicSlaveClient();
       
   120     /**
       
   121      * Second stage constructor - install the device
       
   122      */
       
   123     virtual TInt Install();
       
   124     /**
       
   125      * Get the Capabilites of the device
       
   126      * @param aDes descriptor that will contain the returned capibilites
       
   127      */
       
   128     virtual void GetCaps(TDes8 &aDes) const;
       
   129     /**
       
   130      * Create a logical channel to the device
       
   131      */
       
   132     virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   133     };
       
   134 
       
   135 
       
   136 class DChannelIicSlaveClient : public DLogicalChannel
       
   137     {
       
   138     public:
       
   139     DChannelIicSlaveClient();
       
   140     ~DChannelIicSlaveClient();
       
   141 
       
   142     virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
       
   143 
       
   144 	void RequestComplete(TInt r);
       
   145 	TInt CheckDataWritten();
       
   146 	TInt CheckDataRead();
       
   147 
       
   148 	static void SlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam);
       
   149 #ifdef STANDALONE_CHANNEL
       
   150 	static TInt OrderEntries(const DIicSlaveClientChan& aMatch, const DIicSlaveClientChan& aEntry);
       
   151 #endif
       
   152     protected:
       
   153     virtual void HandleMsg(TMessageBase* aMsg);	// Note: this is a pure virtual in DLogicalChannel
       
   154 
       
   155 	TInt DoControl(TInt aId, TAny* a1, TAny* a2); // Name for convenience!
       
   156     TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); // Name for convenience!
       
   157 
       
   158 	private:
       
   159 	TInt InitSlaveClient();
       
   160 	TInt CbProcessOverUnderRunRxTx();
       
   161 	TInt RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset);
       
   162 	TInt SetNotificationTrigger(TInt aChannelId, TInt aTrigger);
       
   163 	TInt StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2);
       
   164 	TInt RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset);
       
   165 	TInt CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch=NULL);
       
   166 	TInt ReleaseChannel(TInt aChannelId);
       
   167 	private:
       
   168 	TDynamicDfcQue* iDfcQue;
       
   169 	TIicBusSlaveCallback* iNotif;
       
   170 
       
   171 	HBuf8* iConfigHdr;
       
   172 	TRequestStatus* iStatus;
       
   173 
       
   174 	TUint8* iRxBuf;
       
   175 	TUint8* iTxBuf;
       
   176 
       
   177 	TUint8* iBusTxCheckBuf;
       
   178 
       
   179 	TInt8 iNumRegRxWords;
       
   180 	TInt8 iNumRegTxWords;
       
   181 
       
   182 	TInt8 iTxRegGranularity;
       
   183 	TInt8 iTxRegOffset;
       
   184 	TInt8 iTxReqNumWords;
       
   185 
       
   186 	TInt8 iRxRegGranularity;
       
   187 	TInt8 iRxRegOffset;
       
   188 	TInt8 iRxReqNumWords;
       
   189 
       
   190 	TUint iBusId;
       
   191 #ifdef STANDALONE_CHANNEL
       
   192 	// For some slave-channel-only functions,e.g. ReleaseChannel, RegisterRxBuffer, etc.
       
   193 	// the client needs to remember the slave channel that has been captured
       
   194 	struct TCapturedChannel
       
   195 		{
       
   196 		DIicSlaveClientChan* iChannel;
       
   197 		TInt iChannelId;
       
   198 		};
       
   199 	TCapturedChannel iCapturedChan;
       
   200 #endif
       
   201 	public:
       
   202 	DThread* iClient;
       
   203 	TInt iChannelId;	// public to be accessible by callback
       
   204 	TInt* iClientChanId;
       
   205 
       
   206 	TInt iExpectedTrigger;
       
   207 	TInt iFullDuplexReq;
       
   208 	TInt iBlockedTrigger;
       
   209 
       
   210 	typedef enum TTestOverUnderState
       
   211 		{
       
   212 		EStartState  = 0x1,
       
   213 		ERxOverrun_1,
       
   214 		ERxOverrun_2,
       
   215 		ETxUnderrun_1,
       
   216 		ETxUnderrun_2
       
   217 		};
       
   218 	TTestOverUnderState iTestOverUnderState;
       
   219 	};
       
   220 
       
   221 DDeviceIicSlaveClient::DDeviceIicSlaveClient()
       
   222 // Constructor
       
   223     {
       
   224 	CLIENT_PRINT(("> DDeviceIicSlaveClient::DDeviceIicSlaveClient()"));
       
   225     iParseMask=0;		// No info, no PDD, no Units
       
   226     iUnitsMask=0;
       
   227     iVersion=TVersion(KIicClientMajorVersionNumber,
       
   228 		      KIicClientMinorVersionNumber,
       
   229 		      KIicClientBuildVersionNumber);
       
   230     }
       
   231 
       
   232 #ifdef STANDALONE_CHANNEL
       
   233 //Store all the channels created by the client into an array
       
   234 RPointerArray<DIicSlaveClientChan> ChannelArray;
       
   235 #endif
       
   236 DDeviceIicSlaveClient::~DDeviceIicSlaveClient()
       
   237 // Destructor
       
   238     {
       
   239 	CLIENT_PRINT(("> DDeviceIicSlaveClient::~DDeviceIicSlaveClient()"));
       
   240 #ifdef STANDALONE_CHANNEL
       
   241 	//The client is reponsible for channel destroy in STANDALONE_CHANNEL mode
       
   242     ChannelArray.ResetAndDestroy();
       
   243 #endif
       
   244 	}
       
   245 
       
   246 TInt DDeviceIicSlaveClient::Install()
       
   247 // Install the device driver.
       
   248     {
       
   249 	CLIENT_PRINT(("> DDeviceIicSlaveClient::Install()"));
       
   250 
       
   251     return(SetName(&KLddRootName));
       
   252     }
       
   253 
       
   254 
       
   255 void DDeviceIicSlaveClient::GetCaps(TDes8& aDes) const
       
   256 // Return the IicClient capabilities.
       
   257     {
       
   258 	CLIENT_PRINT(("> DDeviceIicSlaveClient::GetCaps(TDes8& aDes) const"));
       
   259     TPckgBuf<TCapsIicSlaveClient> b;
       
   260     b().version=TVersion(KIicClientMajorVersionNumber,
       
   261 			 KIicClientMinorVersionNumber,
       
   262 			 KIicClientBuildVersionNumber);
       
   263     Kern::InfoCopy(aDes,b);
       
   264     }
       
   265 
       
   266 
       
   267 TInt DDeviceIicSlaveClient::Create(DLogicalChannelBase*& aChannel)
       
   268 // Create a channel on the device.
       
   269     {
       
   270 	CLIENT_PRINT(("> DDeviceIicSlaveClient::Create(DLogicalChannelBase*& aChannel)"));
       
   271 	if(iOpenChannels>=KMaxNumChannels)
       
   272 		return KErrOverflow;
       
   273     aChannel=new DChannelIicSlaveClient;
       
   274     return aChannel?KErrNone:KErrNoMemory;
       
   275     }
       
   276 
       
   277 #ifdef STANDALONE_CHANNEL
       
   278 //  auxiliary function for ordering entries in the array of channels
       
   279 TInt DChannelIicSlaveClient::OrderEntries(const DIicSlaveClientChan& aMatch, const DIicSlaveClientChan& aEntry)
       
   280 	{
       
   281 	TUint8 l=(TUint8)aMatch.GetChanNum();
       
   282 	TUint8 r=(TUint8)aEntry.GetChanNum();
       
   283 	if(l>r)
       
   284 		return -1;
       
   285 	else if(l<r)
       
   286 		return 1;
       
   287 	else
       
   288 		return 0;
       
   289 	}
       
   290 
       
   291 // global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
       
   292 TLinearOrder<DIicSlaveClientChan> EntryOrder(DChannelIicSlaveClient::OrderEntries);
       
   293 
       
   294 TInt GetChanPtr(const TInt aBusId, DIicSlaveClientChan*& aChan)
       
   295 	{
       
   296     __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
       
   297 	TInt32 chanId;
       
   298 	chanId = GET_CHAN_NUM(aBusId);
       
   299     __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, chanId=0x%x\n",chanId));
       
   300 	DIicSlaveClientChan chanEntry(NULL,(TInt8)chanId, DIicBusChannel::EMasterSlave);
       
   301 
       
   302 	TInt r = KErrNotFound;
       
   303 	TInt aIndex = ChannelArray.FindInOrder(&chanEntry, EntryOrder);
       
   304 
       
   305 	if(aIndex >= 0)
       
   306 		{
       
   307 		aChan = ChannelArray[aIndex];
       
   308 		r = KErrNone;
       
   309 		}
       
   310 
       
   311 	return r;
       
   312 	}
       
   313 #endif/*STANDALONE_CHANNEL*/
       
   314 
       
   315 DECLARE_STANDARD_LDD()
       
   316 	{
       
   317 #ifdef STANDALONE_CHANNEL
       
   318 	TInt r = KErrNone;
       
   319 	DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
       
   320 	DIicSlaveClientChan* aSlaveClientChan;
       
   321 	for(TInt i=0; i<NUM_CHANNELS; i++)
       
   322 			{
       
   323 			CLIENT_PRINT(("\n"));
       
   324 	#if defined(MASTER_MODE)
       
   325 			if(CHANNEL_TYPE(i) == (DIicBusChannel::EMaster))
       
   326 				{
       
   327 				chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
       
   328 				if(!chan)
       
   329 					{
       
   330 					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
       
   331 					return NULL;
       
   332 					}
       
   333 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   334 				if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
       
   335 					{
       
   336 					delete chan;
       
   337 					return NULL;
       
   338 					}
       
   339 				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
       
   340 				if(!aSlaveClientChan)
       
   341 					{
       
   342 					delete chan;
       
   343 					return NULL;
       
   344 					}
       
   345 				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
       
   346 				if(r!=KErrNone)
       
   347 					{
       
   348 					delete chan;
       
   349 					delete aSlaveClientChan;
       
   350 					break;
       
   351 					}
       
   352 				}
       
   353 	#endif
       
   354 	#if defined(MASTER_MODE) && defined(SLAVE_MODE)
       
   355 			if(CHANNEL_TYPE(i) == DIicBusChannel::EMasterSlave)
       
   356 				{
       
   357 				chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
       
   358 				if(!chanM)
       
   359 					return NULL;
       
   360 				chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
       
   361 				if(!chanS)
       
   362 					{
       
   363 					delete chanM;
       
   364 					return NULL;
       
   365 					}
       
   366 				chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
       
   367 				if(!chan)
       
   368 					{
       
   369 					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
       
   370 					delete chanM;
       
   371 					delete chanS;
       
   372 					return NULL;
       
   373 					}
       
   374 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   375 				if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
       
   376 					{
       
   377 					delete chanM;
       
   378 					delete chanS;
       
   379 					delete chan;
       
   380 					return NULL;
       
   381 					}
       
   382 				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
       
   383 				if(!aSlaveClientChan)
       
   384 					{
       
   385 					delete chanM;
       
   386 					delete chanS;
       
   387 					delete chan;
       
   388 					return NULL;
       
   389 					}
       
   390 				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
       
   391 				if(r!=KErrNone)
       
   392 					{
       
   393 					delete chanM;
       
   394 					delete chanS;
       
   395 					delete chan;
       
   396 					delete aSlaveClientChan;
       
   397 					break;
       
   398 					}
       
   399 				}
       
   400 	#endif
       
   401 	#if defined(SLAVE_MODE)
       
   402 			if(CHANNEL_TYPE(i) == (DIicBusChannel::ESlave))
       
   403 				{
       
   404 				chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
       
   405 				if(!chan)
       
   406 					{
       
   407 					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
       
   408 					return NULL;
       
   409 					}
       
   410 				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
       
   411 				if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
       
   412 					return NULL;
       
   413 				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
       
   414 				if(!aSlaveClientChan)
       
   415 					{
       
   416 					delete chan;
       
   417 					return NULL;
       
   418 					}
       
   419 				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
       
   420 				if(r!=KErrNone)
       
   421 					{
       
   422 					delete chan;
       
   423 					delete aSlaveClientChan;
       
   424 					break;
       
   425 					}
       
   426 				}
       
   427 	#endif
       
   428 	#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
       
   429 	#error I2C mode not defined as Master, Slave nor Master-Slave
       
   430 	#endif
       
   431 			}
       
   432 #endif
       
   433 	return new DDeviceIicSlaveClient;
       
   434 	}
       
   435 
       
   436 
       
   437 
       
   438 DChannelIicSlaveClient::DChannelIicSlaveClient()
       
   439 // Constructor
       
   440     {
       
   441 	iFullDuplexReq=iBlockedTrigger=iExpectedTrigger=0;
       
   442 	CLIENT_PRINT(("> DChannelIicSlaveClient::DChannelIicSlaveClient()"));
       
   443     iClient=&Kern::CurrentThread();
       
   444 	// Increase the DThread's ref count so that it does not close without us
       
   445 	iClient->Open();
       
   446 	iTestOverUnderState = EStartState;
       
   447     }
       
   448 
       
   449 DChannelIicSlaveClient::~DChannelIicSlaveClient()
       
   450 // Destructor
       
   451     {
       
   452 	CLIENT_PRINT(("> DChannelIicSlaveClient::~DChannelIicSlaveClient()"));
       
   453 	iDfcQue->Destroy();
       
   454 	delete iNotif;
       
   455 	delete iRxBuf;
       
   456 	delete iTxBuf;
       
   457 	delete iBusTxCheckBuf;
       
   458 	// decrement the DThread's reference count
       
   459 	Kern::SafeClose((DObject*&)iClient, NULL);
       
   460 	}
       
   461 
       
   462 void DChannelIicSlaveClient::RequestComplete(TInt r)
       
   463 	{
       
   464 	Kern::RequestComplete(iClient, iStatus, r);
       
   465 	}
       
   466 
       
   467 TInt DChannelIicSlaveClient::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
       
   468 	{
       
   469 	TInt r = KErrNone;
       
   470 #ifdef STANDALONE_CHANNEL
       
   471 	DIicSlaveClientChan* aChanPtr = NULL;
       
   472 	if(iCapturedChan.iChannelId == aChannelId)
       
   473 		aChanPtr = iCapturedChan.iChannel;
       
   474 	if(!aChanPtr)
       
   475 		return KErrArgument;
       
   476 	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
       
   477 		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->RegisterRxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
       
   478 	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
       
   479 		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->RegisterRxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
       
   480 #else
       
   481 	r = IicBus::RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
       
   482 #endif
       
   483 	return r;
       
   484 	}
       
   485 
       
   486 TInt DChannelIicSlaveClient::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
       
   487 	{
       
   488 	TInt r = KErrNone;
       
   489 #ifdef STANDALONE_CHANNEL
       
   490 	DIicSlaveClientChan* aChanPtr = NULL;
       
   491 	if(iCapturedChan.iChannelId == aChannelId)
       
   492 		aChanPtr = iCapturedChan.iChannel;
       
   493 	if(!aChanPtr)
       
   494 		return KErrArgument;
       
   495 	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
       
   496 		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->SetNotificationTrigger(aTrigger);
       
   497 	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
       
   498 		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->SetNotificationTrigger(aTrigger);
       
   499 #else
       
   500 	r = IicBus::SetNotificationTrigger(aChannelId, aTrigger);
       
   501 #endif
       
   502 	return r;
       
   503 	}
       
   504 
       
   505 TInt DChannelIicSlaveClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
       
   506 	{
       
   507 	TInt r = KErrNone;
       
   508 #ifdef STANDALONE_CHANNEL
       
   509 	DIicSlaveClientChan* aChanPtr;
       
   510 	r = GetChanPtr(aId, aChanPtr);
       
   511 	if(r != KErrNone)
       
   512 		return r;
       
   513 	if(!aChanPtr)
       
   514 		return KErrArgument;
       
   515 	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
       
   516 		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->StaticExtension(aFunction, aParam1, aParam2);
       
   517 	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
       
   518 	r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->StaticExtension(aFunction, aParam1, aParam2);
       
   519 #else
       
   520 	r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
       
   521 #endif
       
   522 	return r;
       
   523 	}
       
   524 
       
   525 TInt DChannelIicSlaveClient::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
       
   526 	{
       
   527 	TInt r = KErrNone;
       
   528 #ifdef STANDALONE_CHANNEL
       
   529 	DIicSlaveClientChan* aChanPtr = NULL;
       
   530 	if(iCapturedChan.iChannelId == aChannelId)
       
   531 		aChanPtr = iCapturedChan.iChannel;
       
   532 	if(!aChanPtr)
       
   533 		return KErrArgument;
       
   534 	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
       
   535 		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset);
       
   536 	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
       
   537 		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset);
       
   538 #else
       
   539 	r = IicBus::RegisterTxBuffer(aChannelId, aTxBuffer, aBufGranularity, aNumWords, aOffset);
       
   540 #endif
       
   541 	return r;
       
   542 	}
       
   543 
       
   544 TInt DChannelIicSlaveClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
       
   545 	{
       
   546 	TInt r = KErrNone;
       
   547 #ifndef STANDALONE_CHANNEL
       
   548 	r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
       
   549 #else
       
   550 	// Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
       
   551 	if(!aCallback || !aConfigHdr)
       
   552 		{
       
   553 		return KErrArgument;
       
   554 		}
       
   555 
       
   556 	// Get the channel
       
   557 	DIicSlaveClientChan* chanPtr = NULL;
       
   558 	if(r == KErrNone)
       
   559 		{
       
   560 		r = GetChanPtr(aBusId, chanPtr);
       
   561 		if(r == KErrNone)
       
   562 			{
       
   563 			if(!chanPtr)
       
   564 				{
       
   565 				r = KErrArgument;
       
   566 				}
       
   567 			else
       
   568 				{
       
   569 				switch(chanPtr->GetChanType())
       
   570 					{
       
   571 					// CaptureChannel requests are only supported by channels in Slave mode.
       
   572 					case DIicBusChannel::EMaster:
       
   573 						{
       
   574 						r = KErrNotSupported;
       
   575 						break;
       
   576 						}
       
   577 					case DIicBusChannel::EMasterSlave:
       
   578 						{
       
   579 						r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
       
   580 						break;
       
   581 						}
       
   582 					case DIicBusChannel::ESlave:
       
   583 						{
       
   584 						r = ((DIicBusChannelSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
       
   585 						break;
       
   586 						}
       
   587 					default:
       
   588 						{
       
   589 						r = KErrArgument;
       
   590 						}
       
   591 					}
       
   592 				// For synchronous capture, if successful then install the channel
       
   593 				if(r == KErrNone)
       
   594 					{
       
   595 					if(!aAsynch)
       
   596 						{
       
   597 						 iCapturedChan.iChannel = chanPtr;
       
   598 						 iCapturedChan.iChannelId = aChannelId;
       
   599 						}
       
   600 					else
       
   601 						//For asynchronous capture, record slaveChanPtr, if later failed capture,
       
   602 						//clean iCapturedChannel in client's callback.
       
   603 						iCapturedChan.iChannel = chanPtr;
       
   604 					}
       
   605 				}
       
   606 			}
       
   607 		}
       
   608 #endif
       
   609 	return r;
       
   610 	}
       
   611 
       
   612 TInt DChannelIicSlaveClient::ReleaseChannel(TInt aChannelId)
       
   613 	{
       
   614 	TInt r = KErrNone;
       
   615 #ifndef STANDALONE_CHANNEL
       
   616 	r = IicBus::ReleaseChannel(aChannelId);
       
   617 #else
       
   618     __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicSlaveClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
       
   619     // Acquire the pointer to the Slave Channel
       
   620     if(iCapturedChan.iChannelId != aChannelId)
       
   621 		return KErrNotFound;
       
   622 
       
   623 	if((iCapturedChan.iChannel)->GetChanType() == DIicBusChannel::EMasterSlave)
       
   624 		r = ((DIicBusChannelMasterSlave*)((iCapturedChan.iChannel)->GetChannelPtr()))->ReleaseChannel();
       
   625 	else if((iCapturedChan.iChannel)->GetChanType() == DIicBusChannel::ESlave)
       
   626 		r = ((DIicBusChannelSlave*)((iCapturedChan.iChannel)->GetChannelPtr()))->ReleaseChannel();
       
   627 	//After release channel, reset iCapturedChan
       
   628 	iCapturedChan.iChannel = NULL;
       
   629 	iCapturedChan.iChannelId = 0;
       
   630 #endif
       
   631 	return r;
       
   632 	}
       
   633 TInt DChannelIicSlaveClient::CbProcessOverUnderRunRxTx()
       
   634 	{
       
   635 	CLIENT_PRINT(("> DChannelIicSlaveClient::CbProcessOverUnderRunRxTx(), iTestOverUnderState=%d\n",iTestOverUnderState));
       
   636 	TInt r = KErrNone;
       
   637 	switch (iTestOverUnderState)
       
   638 		{
       
   639 		case(EStartState):
       
   640 			{
       
   641 			// In this state, no action is required
       
   642 			break;
       
   643 			};
       
   644 		case(ERxOverrun_1):
       
   645 			{
       
   646 			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ERxOverrun_1\n"));
       
   647 			// At this point, the outstanding request trigger should be ETxAllBytes | ETxUnderrun
       
   648 			// and the flag to indicate duplex transfers should be cleared
       
   649 			if((iExpectedTrigger != (ETxAllBytes | ETxUnderrun)) || (iFullDuplexReq != ETxAllBytes))
       
   650 				{
       
   651 				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
       
   652 				r=KErrGeneral;
       
   653 				}
       
   654 			else
       
   655 				{
       
   656 				// Simulate providing a new buffer (actually, re-use existing buffer)
       
   657 				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
       
   658 				TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
       
   659 				r = RegisterRxBuffer(iChannelId, rxPtr, iRxRegGranularity, iNumRegRxWords, iRxRegOffset);
       
   660 
       
   661 				if(r != KErrNone)
       
   662 					{
       
   663 					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterRxBuffer returned %d\n",r));
       
   664 					}
       
   665 				else
       
   666 					{
       
   667 					// For the next step, just specify the new Rx triggers (do not specify Tx triggers)
       
   668 					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun));
       
   669 					if(r != KErrNone)
       
   670 						{
       
   671 						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d\n",r));
       
   672 						}
       
   673 					else
       
   674 						{
       
   675 						iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
       
   676 						iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
   677 						iTestOverUnderState = ERxOverrun_2;	// Prepare for callback
       
   678 						// The requested number of words when the buffer was registered was 8, so simulate 10
       
   679 						// to provoke an RxOverrun event.
       
   680 						TInt numWords=10;
       
   681 						// To support testing, any values of aId for StaticExtension must be shifted left one place
       
   682 						// and for a Slave, the two msbs must be zero
       
   683 						TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxWords;
       
   684 						ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
       
   685 						r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
       
   686 						}
       
   687 					}
       
   688 				}
       
   689 			break;
       
   690 			};
       
   691 		case(ERxOverrun_2):
       
   692 			{
       
   693 			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ERxOverrun_2\n"));
       
   694 			// At this point, the outstanding request trigger should be ETxAllBytes | ETxUnderrun
       
   695 			// and the flag to indicate duplex transfers should be cleared
       
   696 			if((iExpectedTrigger != (ETxAllBytes | ETxUnderrun)) || (iFullDuplexReq != ETxAllBytes))
       
   697 				{
       
   698 				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
       
   699 				r=KErrGeneral;
       
   700 				}
       
   701 			else
       
   702 				{
       
   703 				// Simulate providing a new buffer (actually, re-use existing buffer)
       
   704 				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
       
   705 				TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
       
   706 				r = RegisterRxBuffer(iChannelId, rxPtr, iRxRegGranularity, iNumRegRxWords, iRxRegOffset);
       
   707 				if(r != KErrNone)
       
   708 					{
       
   709 					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterRxBuffer returned %d\n",r));
       
   710 					}
       
   711 				else
       
   712 					{
       
   713 					// Test that an attempt to modify existing Tx notification requests is rejected
       
   714 					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxOverrun));
       
   715 					if(r != KErrInUse)
       
   716 						{
       
   717 						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrInUse\n",r));
       
   718 						}
       
   719 					else
       
   720 						{
       
   721 						// For the next step, specify the new Rx triggers and the Tx triggers
       
   722 						r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
       
   723 						if(r != KErrNone)
       
   724 							{
       
   725 							CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrNone\n",r));
       
   726 							}
       
   727 						else
       
   728 							{
       
   729 							iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
       
   730 							iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
   731 							iTestOverUnderState = ETxUnderrun_1;	// Prepare for callback
       
   732 							// The requested number of words when the buffer was registered was 12, so simulate 14
       
   733 							// to provoke an TxUnderrun event.
       
   734 							TInt numWords=14;
       
   735 							// To support testing, any values of aId for StaticExtension must be shifted left one place
       
   736 							// and for a Slave, the two msbs must be zero
       
   737 							TInt ctrlIoVal = RBusDevIicClient::ECtrlIoTxWords;
       
   738 							ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
       
   739 							r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
       
   740 							}
       
   741 						}
       
   742 					}
       
   743 				}
       
   744 			break;
       
   745 			};
       
   746 		case(ETxUnderrun_1):
       
   747 			{
       
   748 			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ETxOverrun_1\n"));
       
   749 			// At this point, the outstanding request trigger should be ERxAllBytes | ERxOverrun
       
   750 			// and the flag to indicate duplex transfers should be cleared
       
   751 			if((iExpectedTrigger != (ERxAllBytes | ERxOverrun)) || (iFullDuplexReq != ERxAllBytes))
       
   752 				{
       
   753 				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
       
   754 				r=KErrGeneral;
       
   755 				}
       
   756 			else
       
   757 				{
       
   758 				// Simulate providing a new buffer (actually, re-use existing buffer)
       
   759 				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterTxBuffer\n"));
       
   760 				TPtr8 rxPtr(iTxBuf,KTxBufSizeInBytes);
       
   761 				r = RegisterTxBuffer(iChannelId, rxPtr, iTxRegGranularity, iNumRegTxWords, iTxRegOffset);
       
   762 				if(r != KErrNone)
       
   763 					{
       
   764 					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterTxBuffer returned %d\n",r));
       
   765 					}
       
   766 				else
       
   767 					{
       
   768 					// For the next step, just specify the new Tx triggers (do not specify Rx triggers)
       
   769 					r = SetNotificationTrigger(iChannelId, (ETxAllBytes | ETxUnderrun));
       
   770 					if(r != KErrNone)
       
   771 						{
       
   772 						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d\n",r));
       
   773 						}
       
   774 					else
       
   775 						{
       
   776 						iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
       
   777 						iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
   778 						iTestOverUnderState = ETxUnderrun_2;	// Prepare for callback
       
   779 						// The requested number of words when the buffer was registered was 12, so simulate 14
       
   780 						// to provoke an TxUnderrun event.
       
   781 						TInt numWords=14;
       
   782 						// To support testing, any values of aId for StaticExtension must be shifted left one place
       
   783 						// and for a Slave, the two msbs must be zero
       
   784 						TInt ctrlIoVal = RBusDevIicClient::ECtrlIoTxWords;
       
   785 						ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
       
   786 						r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
       
   787 						}
       
   788 					}
       
   789 				}
       
   790 			break;
       
   791 			};
       
   792 		case(ETxUnderrun_2):
       
   793 			{
       
   794 			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ETxUnderrun_2\n"));
       
   795 			// At this point, the outstanding request trigger should be ERxAllBytes | ERxOverrun
       
   796 			// and the flag to indicate duplex transfers should be cleared
       
   797 			if((iExpectedTrigger != (ERxAllBytes | ERxOverrun)) || (iFullDuplexReq != ERxAllBytes))
       
   798 				{
       
   799 				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
       
   800 				r=KErrGeneral;
       
   801 				}
       
   802 			else
       
   803 				{
       
   804 				// Simulate providing a new buffer (actually, re-use existing buffer)
       
   805 				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
       
   806 				TPtr8 rxPtr(iTxBuf,KTxBufSizeInBytes);
       
   807 				r = RegisterTxBuffer(iChannelId, rxPtr, iTxRegGranularity, iNumRegTxWords, iTxRegOffset);
       
   808 				if(r != KErrNone)
       
   809 					{
       
   810 					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterTxBuffer returned %d\n",r));
       
   811 					}
       
   812 				else
       
   813 					{
       
   814 					// Test that an attempt to modify existing Rx notification requests is rejected
       
   815 					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxUnderrun | ETxAllBytes | ETxUnderrun));
       
   816 					if(r != KErrInUse)
       
   817 						{
       
   818 						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrInUse\n",r));
       
   819 						}
       
   820 					else
       
   821 						{
       
   822 						// For the next step, specify the new Rx triggers and the Tx triggers
       
   823 						r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
       
   824 
       
   825 						if(r != KErrNone)
       
   826 							{
       
   827 							CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrNone\n",r));
       
   828 							}
       
   829 						else
       
   830 							{
       
   831 							// Simulate a simultaneous ERxAllBytes and ETxAllBytes event.
       
   832 							iExpectedTrigger = ERxAllBytes | ETxAllBytes;
       
   833 							iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
   834 							iTestOverUnderState = EStartState;	// Prepare for callback - return to normal operation
       
   835 							// Need to pass the number of words in an array, for use by StaticExtension
       
   836 							TInt parms[2];
       
   837 							parms[0]= 8;	// Number of Rx Words
       
   838 							parms[1]=12;	// Number of Tx Words
       
   839 							// To support testing, any values of aId for StaticExtension must be shifted left one place
       
   840 							// and for a Slave, the two msbs must be zero
       
   841 							TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxTxWords;
       
   842 							ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
       
   843 							r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)(&parms[0]));
       
   844 							}
       
   845 						}
       
   846 					}
       
   847 				}
       
   848 			break;
       
   849 			};
       
   850 		default:
       
   851 			{
       
   852 			r = KErrGeneral;
       
   853 			break;
       
   854 			};
       
   855 		}
       
   856 	return r;
       
   857 	}
       
   858 
       
   859 void DChannelIicSlaveClient::SlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam)
       
   860 	{
       
   861 	CLIENT_PRINT(("> SlaveClientCallbackFunc() - aChannelId=0x%x,aReturn=%d,aTrigger=0x%x,aRxWords=0x%x,aTxWords=0x%x,aParam=0x%x\n",aChannelId,aReturn,aTrigger,aRxWords,aTxWords,aParam));
       
   862 	(void)aTxWords; // Unused if CLIENT_PRINT is undefined
       
   863 	(void)aRxWords; // Unused if CLIENT_PRINT is undefined
       
   864 	DChannelIicSlaveClient* channel = (DChannelIicSlaveClient*)aParam;
       
   865 
       
   866 	// Ensure only the valid bits of aTrigger are processed
       
   867 	aTrigger &= 0xff;
       
   868 
       
   869 	CLIENT_PRINT(("SlaveClientCallbackFunc() - channel=0x%x\n",channel));
       
   870 	if(aTrigger == EAsyncCaptChan)
       
   871 		{
       
   872 		CLIENT_PRINT(("SlaveClientCallbackFunc: capture channel completed\n"));
       
   873 		// Set iChannelId, and write to user-side variable.
       
   874 		channel->iChannelId=aChannelId;
       
   875 		TInt r=Kern::ThreadRawWrite(channel->iClient,channel->iClientChanId,&aChannelId,sizeof(TInt));
       
   876 		if(r == KErrNone)
       
   877 			r=aReturn;
       
   878 #ifdef STANDALONE_CHANNEL
       
   879 		// Set the captured channel's iChannelId if the capture succeeds.
       
   880 		if(r != KErrCompletion)
       
   881 			(channel->iCapturedChan).iChannel = NULL;
       
   882 		else
       
   883 			(channel->iCapturedChan).iChannelId = aChannelId;
       
   884 #endif/*STANDALONE_CHANNEL*/
       
   885 	    channel->RequestComplete(r);	// Inform user of error
       
   886 		return;
       
   887 		}
       
   888 	else
       
   889 		{
       
   890 		if(aTrigger&ERxAllBytes)
       
   891 			{
       
   892 			CLIENT_PRINT(("SlaveClientCallbackFunc() - ERxAllBytes\n"));
       
   893 			aTrigger&= ~ERxAllBytes;
       
   894 			channel->iExpectedTrigger&=~ERxAllBytes;
       
   895 			channel->iFullDuplexReq&=~ERxAllBytes;
       
   896 			aReturn=channel->CheckDataRead();
       
   897 			// Check underrun
       
   898 			if(aTrigger&ERxUnderrun)
       
   899 				{
       
   900 				if(channel->iExpectedTrigger&ERxUnderrun)
       
   901 					{
       
   902 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxUnderrun found OK\n\n"));
       
   903 					channel->iExpectedTrigger&=~ERxUnderrun;
       
   904 					}
       
   905 				else
       
   906 					{
       
   907 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ERxUnderrun indicated\n\n"));
       
   908 					aReturn = KErrGeneral;
       
   909 					}
       
   910 				}
       
   911 			else
       
   912 				{
       
   913 				if(channel->iExpectedTrigger&ERxUnderrun)
       
   914 					{
       
   915 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxUnderrun not (yet) seen\n\n"));
       
   916 					aReturn = KErrGeneral;
       
   917 					}
       
   918 				}
       
   919 			// Check overrun
       
   920 			if(aTrigger&ERxOverrun)
       
   921 				{
       
   922 				if(channel->iExpectedTrigger&ERxOverrun)
       
   923 					{
       
   924 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxOverrun found OK\n\n"));
       
   925 					channel->iExpectedTrigger&=~ERxOverrun;
       
   926 					}
       
   927 				else
       
   928 					{
       
   929 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ERxOverrun indicated\n\n"));
       
   930 					aReturn = KErrGeneral;
       
   931 					}
       
   932 				}
       
   933 			else
       
   934 				{
       
   935 				if(channel->iExpectedTrigger&ERxOverrun)
       
   936 					{
       
   937 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxOverrun not (yet) seen\n\n"));
       
   938 					aReturn = KErrGeneral;
       
   939 					}
       
   940 				}
       
   941 			}
       
   942 
       
   943 		if(aTrigger&ETxAllBytes)
       
   944 			{
       
   945 			CLIENT_PRINT(("SlaveClientCallbackFunc() - ETxAllBytes\n"));
       
   946 			aTrigger&= ~ETxAllBytes;
       
   947 			channel->iExpectedTrigger&=~ETxAllBytes;
       
   948 			channel->iFullDuplexReq&=~ETxAllBytes;
       
   949 			aReturn=channel->CheckDataWritten();
       
   950 			// Check underrun
       
   951 			if(aTrigger&ETxUnderrun)
       
   952 				{
       
   953 				if(channel->iExpectedTrigger&ETxUnderrun)
       
   954 					{
       
   955 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxUnderrun found OK\n\n"));
       
   956 					channel->iExpectedTrigger&=~ETxUnderrun;
       
   957 					}
       
   958 				else
       
   959 					{
       
   960 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ETxUnderrun indicated\n\n"));
       
   961 					aReturn = KErrGeneral;
       
   962 					}
       
   963 				}
       
   964 			else
       
   965 				{
       
   966 				if(channel->iExpectedTrigger&ETxUnderrun)
       
   967 					{
       
   968 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxUnderrun not (yet) seen\n\n"));
       
   969 					aReturn = KErrGeneral;
       
   970 					}
       
   971 				}
       
   972 			// Check overrun
       
   973 			if(aTrigger&ETxOverrun)
       
   974 				{
       
   975 				if(channel->iExpectedTrigger&ETxOverrun)
       
   976 					{
       
   977 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxOverrun found OK\n\n"));
       
   978 					channel->iExpectedTrigger&=~ETxOverrun;
       
   979 					}
       
   980 				else
       
   981 					{
       
   982 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ETxOverrun indicated\n\n"));
       
   983 					aReturn = KErrGeneral;
       
   984 					}
       
   985 				}
       
   986 			else
       
   987 				{
       
   988 				if(channel->iExpectedTrigger&ETxOverrun)
       
   989 					{
       
   990 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxOverrun not (yet) seen\n\n"));
       
   991 					aReturn = KErrGeneral;
       
   992 					}
       
   993 				}
       
   994 			}
       
   995 
       
   996 
       
   997 		if(aTrigger&EGeneralBusError)
       
   998 			{
       
   999 				if(channel->iExpectedTrigger&EGeneralBusError)
       
  1000 					{
       
  1001 					CLIENT_PRINT(("\nSlaveClientCallbackFunc: EGeneralBusError - as expected\n\n"));
       
  1002 					channel->iExpectedTrigger&=~EGeneralBusError;
       
  1003 					if(aReturn == KErrGeneral)
       
  1004 						{
       
  1005 						aReturn=KErrNone; // If aReturn==KErrGeneral, set to KErrNone so t_iic knows test was successful
       
  1006 						channel->iFullDuplexReq = 0; // The transaction is considered terminated, so don't wait for more triggers
       
  1007 						}
       
  1008 					else
       
  1009 						{
       
  1010 						CLIENT_PRINT(("\nSlaveClientCallbackFunc: aReturn not EGeneralBusError, =0x%x \n\n",aReturn));
       
  1011 						aReturn=KErrGeneral;
       
  1012 						}
       
  1013 
       
  1014 					}
       
  1015 				else
       
  1016 					{
       
  1017 					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected EGeneralBusError indicated\n\n"));
       
  1018 					aReturn = KErrGeneral;
       
  1019 					}
       
  1020 			}
       
  1021 
       
  1022 		if((aTrigger < 0)||(aTrigger & (~0xFF)))
       
  1023 			{
       
  1024 			CLIENT_PRINT(("\nSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
       
  1025 			}
       
  1026 
       
  1027 		// For simulataneous Rx,Tx triggers with ERxOverrun or TxUnderrun testing, need to call the following
       
  1028 		if(aReturn == KErrNone)
       
  1029 			{
       
  1030 			aReturn = channel->CbProcessOverUnderRunRxTx();
       
  1031 			}
       
  1032 
       
  1033 		if((channel->iExpectedTrigger == 0)&&(channel->iFullDuplexReq == 0))
       
  1034 			channel->RequestComplete(aReturn);	// Complete user-side request only if all the triggers have been satisfied
       
  1035 
       
  1036 		} // if(aTrigger == EAsyncCaptChan)
       
  1037 	}
       
  1038 
       
  1039 
       
  1040 TInt DChannelIicSlaveClient::CheckDataRead()
       
  1041 	{
       
  1042 	TInt r=KErrNone;
       
  1043 	// This channel will have provided a buffer for writing to, with a specified offset and number of words
       
  1044 	// Bytes in the buffer before the offset should be set to zero
       
  1045 	// Bytes written at and beyond the offset should exhibit an incrementing count
       
  1046 	// Bytes beyond the offset that were not written to should be set to zero
       
  1047 	TInt8 numWords=(iRxReqNumWords>iNumRegRxWords)?iNumRegRxWords:iRxReqNumWords;
       
  1048 	TInt8 currVal=0;
       
  1049 	TInt8 index = 0;
       
  1050 	while(index<iRxRegOffset)
       
  1051 		{
       
  1052 		currVal=*(iRxBuf+index);
       
  1053 		if(currVal != 0)
       
  1054 			{
       
  1055 			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0",index,currVal));
       
  1056 			r=KErrCorrupt;
       
  1057 			}
       
  1058 		++index;
       
  1059 		}
       
  1060 
       
  1061 	TInt8 checkVal=0x10; // first value written by simulated bus channel
       
  1062 	TInt8 endOfData= (TInt8)(iRxRegOffset+(numWords*iRxRegGranularity));
       
  1063 	TInt8 wordCount=0;
       
  1064 	while(index<endOfData)
       
  1065 		{
       
  1066 		currVal = *(iRxBuf+index);
       
  1067 		if(checkVal != currVal)
       
  1068 			{
       
  1069 			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0x%x",index,currVal,checkVal));
       
  1070 			r=KErrCorrupt;
       
  1071 			}
       
  1072 		if(++wordCount == iRxRegGranularity)
       
  1073 			{
       
  1074 			wordCount=0;
       
  1075 			checkVal++;
       
  1076 			}
       
  1077 		++index;
       
  1078 		}
       
  1079 
       
  1080 	while(index<KRxBufSizeInBytes)
       
  1081 		{
       
  1082 		currVal=*(iRxBuf+index);
       
  1083 		if(currVal != 0)
       
  1084 			{
       
  1085 			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0",index,currVal);)
       
  1086 			r=KErrCorrupt;
       
  1087 			}
       
  1088 		++index;
       
  1089 		}
       
  1090 	return r;
       
  1091 	}
       
  1092 
       
  1093 
       
  1094 TInt DChannelIicSlaveClient::CheckDataWritten()
       
  1095 	{
       
  1096 	TInt r=KErrNone;
       
  1097 	// The pattern in the transmit buffer used by the simulated bus channel contains a incrementing count
       
  1098 	// from 0 to (KTxBufSizeInBytes-1), therefore the first value to be present in the check buffer will be
       
  1099 	// represented by the required offset.
       
  1100 
       
  1101 	// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
       
  1102 	// Since the simulated bus channel is also in the kernel process it shares the same address space
       
  1103 	// Get the address of the buffer
       
  1104 	TUint testId = (((TUint)(RBusDevIicClient::ECtrlIoTxChkBuf))<<1)&0x3FFFFFFF;
       
  1105 	CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten invoking StaticExtension ECtrlIoTxChkBuf with iBusId=0x%x, testId=0x%x, iBusTxCheckBuf=0x%x\n",iBusId,testId,iBusTxCheckBuf));
       
  1106 	r = StaticExtension(iBusId, testId, &iBusTxCheckBuf, NULL);
       
  1107 	if(r!=KErrNone)
       
  1108 		{
       
  1109 		CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten StaticExtension ECtrlIoTxChkBuf returned %d\n",r));
       
  1110 		return r;
       
  1111 		}
       
  1112 
       
  1113 	// Check that the values in the check buffer increment for the
       
  1114 	// required number of words, and that any remaining bytes in the check buffer are set to zero.
       
  1115 	TInt8 firstValue = iTxRegOffset;
       
  1116 	TInt8 currVal = 0;
       
  1117 	TInt8 wordsWritten = 0;
       
  1118 	wordsWritten=(iTxReqNumWords>iNumRegTxWords)?iNumRegTxWords:iTxReqNumWords;
       
  1119 	TInt8 index=0;
       
  1120 	while(index<(wordsWritten*iTxRegGranularity))
       
  1121 		{
       
  1122 		currVal=*(iBusTxCheckBuf+index);
       
  1123 		if(currVal != (TInt8)(firstValue+index))
       
  1124 			{
       
  1125 			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten, index=%d, value =0x%x, expected 0x%x",index,currVal,(TInt8)(firstValue+index)));
       
  1126 			r=KErrCorrupt;
       
  1127 			}
       
  1128 		++index;
       
  1129 		}
       
  1130 	while(index<(iNumRegTxWords*iTxRegGranularity))
       
  1131 		{
       
  1132 		currVal=*(iBusTxCheckBuf+index);
       
  1133 		if(currVal != 0)
       
  1134 			{
       
  1135 			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten, index=%d, value =0x%x, expected 0",index,currVal));
       
  1136 			r=KErrCorrupt;
       
  1137 			}
       
  1138 		++index;
       
  1139 		}
       
  1140 	return r;
       
  1141 	}
       
  1142 
       
  1143 
       
  1144 TInt DChannelIicSlaveClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
  1145 	{
       
  1146 	CLIENT_PRINT(("> DChannelIicSlaveClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
       
  1147 
       
  1148 	TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicSlaveClientThreadPriority,KIicSlaveClientThreadName);
       
  1149 	if(r!=KErrNone)
       
  1150 		return r;
       
  1151 	SetDfcQ(iDfcQue);
       
  1152 
       
  1153 	// Allocate buffers for Rx, Tx operations
       
  1154 	iRxBuf = new TUint8[KRxBufSizeInBytes];
       
  1155 	iTxBuf = new TUint8[KTxBufSizeInBytes];
       
  1156 	if((iRxBuf == NULL)||(iTxBuf == NULL))
       
  1157 		return KErrNoMemory;
       
  1158 	// Start receiving messages
       
  1159 	iMsgQ.Receive();
       
  1160 
       
  1161 	return r;
       
  1162 	}
       
  1163 
       
  1164 TInt DChannelIicSlaveClient::InitSlaveClient()
       
  1165 	{
       
  1166 	iNotif = new TIicBusSlaveCallback(DChannelIicSlaveClient::SlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
       
  1167 	if(iNotif == NULL)
       
  1168 		{
       
  1169 		CLIENT_PRINT(("> DChannelIicSlaveClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
       
  1170 		return KErrNoMemory;
       
  1171 		}
       
  1172 	return KErrNone;
       
  1173 	}
       
  1174 
       
  1175 void DChannelIicSlaveClient::HandleMsg(TMessageBase* aMsg)
       
  1176 	{
       
  1177     TThreadMessage& m=*(TThreadMessage*)aMsg;
       
  1178     TInt id=m.iValue;
       
  1179 
       
  1180 	CLIENT_PRINT((" >ldd: DChannelIicSlaveClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
       
  1181 
       
  1182 	if (id == (TInt)ECloseMsg)
       
  1183 		{
       
  1184 	    iMsgQ.iMessage->Complete(KErrNone,EFalse);
       
  1185 		return;
       
  1186 		}
       
  1187 
       
  1188     if (id<0)
       
  1189 		{
       
  1190 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
  1191 		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
       
  1192 		if (r!=KErrNone)
       
  1193 			{
       
  1194 	    	Kern::RequestComplete(iClient, pS, r);
       
  1195 			}
       
  1196 		m.Complete(KErrNone,ETrue);
       
  1197 		}
       
  1198     else
       
  1199 	if((id>=0)&&(id!=KMaxTInt))
       
  1200 		{
       
  1201 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
  1202 		m.Complete(r,ETrue);
       
  1203 		}
       
  1204 	}
       
  1205 
       
  1206 
       
  1207 TInt DChannelIicSlaveClient::DoControl(TInt aId, TAny* a1, TAny* a2)
       
  1208 	{
       
  1209 	CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
       
  1210 	TInt r=KErrNone;
       
  1211 	// To support testing, any values of aId for StaticExtension must be shifted left one place
       
  1212 	// and for a Slave, the two msbs must be zero
       
  1213 	TInt ctrlIoVal = 0;
       
  1214 	if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
       
  1215 		ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
       
  1216 
       
  1217 	switch(aId)
       
  1218 		{
       
  1219 		case(RBusDevIicClient::EInitSlaveClient):
       
  1220 			{
       
  1221 			r=InitSlaveClient();
       
  1222 			break;
       
  1223 			}
       
  1224 
       
  1225 		case(RBusDevIicClient::ECaptureChanSync):
       
  1226 			{
       
  1227 			// a1 is a pointer to the TDes8* aConfigHdr
       
  1228 			// a2 is a pointer to TInt* parms[2], where:
       
  1229 			// parms[0]=(TInt*)aBusId;
       
  1230 			// parms[1]=&aChannelId;
       
  1231 			//
       
  1232 			TInt* parms[2];
       
  1233 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
       
  1234 			if(r!=KErrNone)
       
  1235 				break;	// Can't proceed if can't access request parameters
       
  1236 			//
       
  1237 		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
       
  1238 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
       
  1239   			if (hdrSize<=0)
       
  1240 				{
       
  1241 				CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
       
  1242  				r = KErrArgument;
       
  1243  				break;
       
  1244 				}
       
  1245 			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
       
  1246 				return KErrNoMemory;
       
  1247 			r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
       
  1248 			if(r!=KErrNone)
       
  1249 				{
       
  1250 				delete iConfigHdr;
       
  1251 				break;
       
  1252 				}
       
  1253 			// Store the address of the user-side variable to update with the ChannelId
       
  1254 			iClientChanId=parms[1];
       
  1255 
       
  1256 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
       
  1257 			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
       
  1258 			if(r != KErrNone)
       
  1259 			    {
       
  1260 			    delete iConfigHdr;
       
  1261 			    break;
       
  1262 			    }
       
  1263 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
       
  1264 
       
  1265 			r = Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
       
  1266 			if(r != KErrNone)
       
  1267 				delete iConfigHdr;
       
  1268 			break;
       
  1269 			}
       
  1270 
       
  1271 		case(RBusDevIicClient::EReleaseChan):
       
  1272 			{
       
  1273 			// a1 represents TInt aChannelId
       
  1274 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
       
  1275 			r = ReleaseChannel((TInt)a1);
       
  1276 			delete iConfigHdr;
       
  1277 			break;
       
  1278 			}
       
  1279 
       
  1280 		case(RBusDevIicClient::ERegisterRxBuffer):
       
  1281 			{
       
  1282 			// a1 represents TInt aChannelId
       
  1283 			// a2 represents (TAny*) of TInt8 parms[3] where parms[0]=aBufGranularity; parms[1]=aNumWords; parms[2]=aOffset
       
  1284 			TInt8 parms[3];
       
  1285 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt8));
       
  1286 			if(r!=KErrNone)
       
  1287 				break;	// Can't proceed if can't access request parameters
       
  1288 			// Store parameters for checking in the callback
       
  1289 			iRxRegGranularity = parms[0];
       
  1290 			iRxRegOffset= parms[2];
       
  1291 			iNumRegRxWords=parms[1];
       
  1292 
       
  1293 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking RegisterRxBuffer\n"));
       
  1294 			TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
       
  1295 			r = RegisterRxBuffer((TInt)a1, rxPtr, parms[0], parms[1], parms[2]);
       
  1296 			break;
       
  1297 			}
       
  1298 
       
  1299 		case(RBusDevIicClient::ERegisterTxBuffer):
       
  1300 			{
       
  1301 			// a1 represents TInt aChannelId
       
  1302 			// a2 represents (TAny*) of TInt8 parms[3] where parms[0]=aBufGranularity; parms[1]=aNumWords; parms[2]=aOffset
       
  1303 			TInt8 parms[3];
       
  1304 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt8));
       
  1305 			if(r!=KErrNone)
       
  1306 				break;	// Can't proceed if can't access request parameters
       
  1307 			// Store parameters for checking in the callback
       
  1308 			iTxRegGranularity = parms[0];
       
  1309 			iTxRegOffset= parms[2];
       
  1310 			iNumRegTxWords=parms[1];
       
  1311 
       
  1312 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking RegisterTxBuffer\n"));
       
  1313 			TPtr8 txPtr(iTxBuf,KTxBufSizeInBytes);
       
  1314 			r = RegisterTxBuffer((TInt)a1, txPtr, parms[0], parms[1], parms[2]);
       
  1315 			break;
       
  1316 			}
       
  1317 
       
  1318 		case(RBusDevIicClient::ESetNotifTrigger):
       
  1319 			{
       
  1320 			// a1 represents (TAny*) of TRequestStatus* aStatus
       
  1321 			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aTrigger
       
  1322 			TInt parms[2];
       
  1323 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
       
  1324 			if(r!=KErrNone)
       
  1325 				break;	// Can't proceed if can't access request parameters
       
  1326 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking SetNotificationTrigger with aStatus=0x%x, aChannelId=0x%x, aTrigger=0x%x\n",a1,parms[0],parms[1]));
       
  1327 			if(a1 == NULL)
       
  1328 				{
       
  1329 				r = KErrArgument;
       
  1330 				break;
       
  1331 				}
       
  1332 			iStatus=(TRequestStatus*)a1;
       
  1333 			// Set the flags for duplex processing
       
  1334 			if((parms[1]&ERxAllBytes)&&(parms[1]&ETxAllBytes))
       
  1335 				iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
  1336 			r = SetNotificationTrigger(parms[0],parms[1]);
       
  1337 			if(r == KErrTimedOut)
       
  1338 				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
       
  1339 			break;
       
  1340 			}
       
  1341 
       
  1342 		case(RBusDevIicClient::ECtrlIoNotifNoTrigger):
       
  1343 			{
       
  1344 			// a1 represents (TAny*) of aChannelId
       
  1345 			// a2 represents (TAny*) of aTrigger
       
  1346 			TInt chanId = (TInt)a1;
       
  1347 			TInt trigger = (TInt)a2;
       
  1348 			// No TRequestStatus is accessed because the call to SetNotificationTrigger
       
  1349 			// is either with zero (when it is valid to do so), or it is being called with a
       
  1350 			// trigger value that is expected to be rejected.
       
  1351 			r = SetNotificationTrigger(chanId,trigger);
       
  1352 
       
  1353 			if(r == KErrNone)
       
  1354 				{
       
  1355 				if((trigger&ERxAllBytes)&&(trigger&ETxAllBytes))
       
  1356 					iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
  1357 				}
       
  1358 			if(r == KErrTimedOut)
       
  1359 				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
       
  1360 			break;
       
  1361 			}
       
  1362 
       
  1363 		case(RBusDevIicClient::ECtrlIoRxWords):
       
  1364 			{
       
  1365 			// a1 represents TInt aBusId
       
  1366 			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aNumWords
       
  1367 			TInt parms[2];
       
  1368 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
       
  1369 			if(r!=KErrNone)
       
  1370 				break;	// Can't proceed if can't access request parameters
       
  1371 			// Prepare iRxBuf
       
  1372 			memset(iRxBuf,0,KRxBufSizeInBytes);
       
  1373 			// Store the number of words for checking in the callback
       
  1374 			iRxReqNumWords=(TInt8)(parms[1]);
       
  1375 
       
  1376 			TInt tempTrigger=0;
       
  1377 			// Set the expected result
       
  1378 			tempTrigger |= ERxAllBytes;
       
  1379 			if(parms[1] < iNumRegRxWords)
       
  1380 				tempTrigger |= ERxUnderrun;
       
  1381 			if(parms[1] > iNumRegRxWords)
       
  1382 				tempTrigger |= ERxOverrun;
       
  1383 			if(iExpectedTrigger != EGeneralBusError)
       
  1384 				iExpectedTrigger |= tempTrigger;
       
  1385 			else
       
  1386 				iBlockedTrigger |= tempTrigger;
       
  1387 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoRxWords) with aBusId=0x%x, aChannelId=0x%x, aNumBytes=0x%x\n",(TInt)a1,parms[0],parms[1]));
       
  1388 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(parms[1]));
       
  1389 			if(r == KErrTimedOut)
       
  1390 				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
       
  1391 			break;
       
  1392 			}
       
  1393 
       
  1394 		case(RBusDevIicClient::ECtrlIoTxWords):
       
  1395 			{
       
  1396 			// a1 represents TInt aBusId
       
  1397 			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aNumWords
       
  1398 			TInt parms[2];
       
  1399 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
       
  1400 			if(r!=KErrNone)
       
  1401 				break;	// Can't proceed if can't access request parameters
       
  1402 			// Prepare iTxBuf
       
  1403 			TUint8* ptr=iTxBuf;
       
  1404 			for(TInt offset=0; offset<KRxBufSizeInBytes; ++offset)
       
  1405 				*ptr++=(TUint8)offset;
       
  1406 			// Store the number of words for checking in the callback
       
  1407 			iTxReqNumWords=(TInt8)(parms[1]);
       
  1408 			TInt tempTrigger=0;
       
  1409 			// Set the expected result
       
  1410 			tempTrigger |= ETxAllBytes;
       
  1411 			if(parms[1] < iNumRegTxWords)
       
  1412 				tempTrigger |= ETxOverrun;
       
  1413 			if(parms[1] > iNumRegTxWords)
       
  1414 				tempTrigger |= ETxUnderrun;
       
  1415 			if(iExpectedTrigger != EGeneralBusError)
       
  1416 				iExpectedTrigger |= tempTrigger;
       
  1417 			else
       
  1418 				iBlockedTrigger |= tempTrigger;
       
  1419 
       
  1420 			// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
       
  1421 			// Since the simulated bus channel is also in the kernel process it shares the same address space
       
  1422 			// Get the address of the buffer
       
  1423 			// As part of the callback invoked by IIC, this client will check the data stored by the simulated
       
  1424 			// bus. Since the simulated bus channel is also in the kernel process it shares the same address space,
       
  1425 			// so the buffer can be accessed directly - but the buffer is not created until it receives the following
       
  1426 			// StaticExtension command, so the bus identifier represented by a1 is stored to allow accessing the buffer
       
  1427 			// adddress from the callback.
       
  1428 			iBusId=(TUint)a1;
       
  1429 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoTxWords) with aBusId=0x%x, aChannelId=0x%x, aNumBytes=0x%x\n",(TInt)a1,parms[0],parms[1]));
       
  1430 			aId<<=1;
       
  1431 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(parms[1]));
       
  1432 			break;
       
  1433 			}
       
  1434 
       
  1435 		case(RBusDevIicClient::ECtrlIoRxTxWords):
       
  1436 			{
       
  1437 			// a1 represents TInt aBusId
       
  1438 			// a2 represents (TAny*) of TInt parms[3] where parms[0]=aChannelId; parms[1]=aNumRxWords; parms[2]=aNumTxWords
       
  1439 			TInt parms[3];
       
  1440 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt));
       
  1441 			if(r!=KErrNone)
       
  1442 				break;	// Can't proceed if can't access request parameters
       
  1443 			// Prepare iRxBuf, iTxBuf
       
  1444 			memset(iRxBuf,0,KRxBufSizeInBytes);
       
  1445 			TUint8* ptr=iTxBuf;
       
  1446 			for(TInt offset=0; offset<KRxBufSizeInBytes; ++offset)
       
  1447 				*ptr++=(TUint8)offset;
       
  1448 
       
  1449 			// Store the number of words for checking in the callback
       
  1450 			iRxReqNumWords=(TInt8)(parms[1]);
       
  1451 			iTxReqNumWords=(TInt8)(parms[2]);
       
  1452 
       
  1453 			TInt tempTrigger=0;
       
  1454 			// Set the expected result
       
  1455 			tempTrigger |= (ERxAllBytes|ETxAllBytes);
       
  1456 
       
  1457 			if(parms[1] < iNumRegRxWords)
       
  1458 				tempTrigger |= ERxUnderrun;
       
  1459 			if(parms[1] > iNumRegRxWords)
       
  1460 				tempTrigger |= ERxOverrun;
       
  1461 
       
  1462 			if(parms[2] < iNumRegTxWords)
       
  1463 				tempTrigger |= ETxOverrun;
       
  1464 			if(parms[2] > iNumRegTxWords)
       
  1465 				tempTrigger |= ETxUnderrun;
       
  1466 
       
  1467 			if(iExpectedTrigger != EGeneralBusError)
       
  1468 				iExpectedTrigger |= tempTrigger;
       
  1469 			else
       
  1470 				iBlockedTrigger |= tempTrigger;
       
  1471 
       
  1472 			// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
       
  1473 			// Since the simulated bus channel is also in the kernel process it shares the same address space
       
  1474 			// Get the address of the buffer
       
  1475 			// As part of the callback invoked by IIC, this client will check the data stored by the simulated
       
  1476 			// bus. Since the simulated bus channel is also in the kernel process it shares the same address space,
       
  1477 			// so the buffer can be accessed directly - but the buffer is not created until it receives the following
       
  1478 			// StaticExtension command, so the bus identifier represented by a1 is stored to allow accessing the buffer
       
  1479 			// adddress from the callback.
       
  1480 			iBusId=(TUint)a1;
       
  1481 
       
  1482 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoRxTxWords) with aBusId=0x%x, aChannelId=0x%x, aNumRxBytes=0x%x, aNumTxBytes=0x%x\n",(TInt)a1,parms[0],parms[1],parms[2]));
       
  1483 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(&(parms[1])));
       
  1484 			if(r == KErrTimedOut)
       
  1485 				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
       
  1486 			break;
       
  1487 			}
       
  1488 
       
  1489 		case(RBusDevIicClient::ECtlIoBusError):
       
  1490 			{
       
  1491 			// a1 represents TInt aBusId
       
  1492 			// a2 represents TInt aChannelId
       
  1493 			// Set the expected result
       
  1494 			iExpectedTrigger |= EGeneralBusError;
       
  1495 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtlIoBusError) \n"));
       
  1496 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
       
  1497 			break;
       
  1498 			}
       
  1499 
       
  1500 		case(RBusDevIicClient::ECtrlIoUnblockNotification):
       
  1501 			{
       
  1502 			// a1 represents TInt aBusId
       
  1503 			// a2 represents TInt aChannelId
       
  1504 			iExpectedTrigger = iBlockedTrigger;
       
  1505 			iBlockedTrigger=0;
       
  1506 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoUnblockNotification) \n"));
       
  1507 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
       
  1508 			break;
       
  1509 			}
       
  1510 
       
  1511 		case(RBusDevIicClient::ECtrlIoBlockNotification):
       
  1512 			{
       
  1513 			// a1 represents TInt aBusId
       
  1514 			// a2 represents TInt aChannelId
       
  1515 			iBlockedTrigger = iExpectedTrigger;
       
  1516 			iExpectedTrigger = EGeneralBusError;	// For this test, just interested in if the timeout is detected
       
  1517 													// iExpectedTrigger will be reinstated prior to unblocking
       
  1518 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoBlockNotification) \n"));
       
  1519 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
       
  1520 			break;
       
  1521 			}
       
  1522 
       
  1523 		case(RBusDevIicClient::ECtrlIoUpdTimeout):
       
  1524 			{
       
  1525 			// a1 represents TInt aBusId
       
  1526 			// a2 represents TInt aChannelId
       
  1527 
       
  1528 			// For this test, instruct the simulated bus to do the following for the Master and Client timeout values:
       
  1529 			// (1) Read the current timeout value and check that it is set to the default
       
  1530 			// (2) Set it to different value
       
  1531 			// (3) Read it back to check success
       
  1532 			// (4) Return to the original value, and readback to confirm
       
  1533 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoBlockNotification) \n"));
       
  1534 			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, NULL, NULL);
       
  1535 			break;
       
  1536 			}
       
  1537 
       
  1538 		default:
       
  1539 			{
       
  1540 			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl - unrecognised value for aId=0x%x\n",aId));
       
  1541 			r=KErrArgument;
       
  1542 			break;
       
  1543 			}
       
  1544 
       
  1545 		}
       
  1546 	return r;
       
  1547 	}
       
  1548 
       
  1549 TInt DChannelIicSlaveClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
  1550 	{
       
  1551 	CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
       
  1552 
       
  1553 	TInt r=KErrNone;
       
  1554 	switch(aId)
       
  1555 		{
       
  1556 		case(RBusDevIicClient::ECaptureChanAsync):
       
  1557 			{
       
  1558 			// a1 is a pointer to the TDes8* aConfigHdr
       
  1559 			// a2 is a pointer to TInt* parms[2], where:
       
  1560 			// parms[0]=(TInt*)aBusId;
       
  1561 			// parms[1]=&aChannelId;
       
  1562 			//
       
  1563 			TInt* parms[2];
       
  1564 			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
       
  1565 			if(r!=KErrNone)
       
  1566 				break;	// Can't proceed if can't access request parameters
       
  1567 			//
       
  1568 		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
       
  1569 			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest hdrSize = 0x%x\n",hdrSize));
       
  1570   			if (hdrSize<=0)
       
  1571 				{
       
  1572 				CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest ERROR, hdrSize is invalid\n"));
       
  1573  				return KErrArgument;
       
  1574 				}
       
  1575 			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
       
  1576 				return KErrNoMemory;
       
  1577 			if((r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0))!=KErrNone)
       
  1578 				{
       
  1579 				delete iConfigHdr;
       
  1580 				return r;
       
  1581 				}
       
  1582 			iStatus=aStatus;
       
  1583 			// Store the address of the user-side variable to update with the ChannelId
       
  1584 			iClientChanId=parms[1];
       
  1585 			// Invoke the IIC API
       
  1586 			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest invoking (asynchronous) CaptureChannel\n"));
       
  1587 			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId, ETrue);
       
  1588 			if(r != KErrNone)
       
  1589 			    delete iConfigHdr;
       
  1590 			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest (asynchronous) CaptureChannel returned %d\n",r));
       
  1591 			break;
       
  1592 			}
       
  1593 
       
  1594 		case(RBusDevIicClient::ECtrlIoOvUndRunRxTx):
       
  1595 			{
       
  1596 			iBusId = (TInt)a1;
       
  1597 			iChannelId = (TInt)a2;
       
  1598 			iStatus=aStatus;
       
  1599 			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest status = 0x%x, busId = 0x%x, chanId =0x%x\n",iStatus,iBusId,iChannelId));
       
  1600 
       
  1601 			// This test is state-machine driven. It is instigated from this point, then subsequent steps
       
  1602 			// are handled in the callback funciton SlaveClientCallbackFunc
       
  1603 			//
       
  1604 			// Check we in the appropriate state to start
       
  1605 			if(iTestOverUnderState == EStartState)
       
  1606 				{
       
  1607 				// Re-use the previously-provided buffers. Just request the initial notification triggers,
       
  1608 				// the simulate the first event (RxOverrun).
       
  1609 				r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
       
  1610 				if(r != KErrNone)
       
  1611 					{
       
  1612 					CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest SetNotificationTrigger returned %d\n",r));
       
  1613 					}
       
  1614 				else
       
  1615 					{
       
  1616 					// Trigger now set, so simulate the required event
       
  1617 					iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
       
  1618 					iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
       
  1619 					iTestOverUnderState = ERxOverrun_1;	// Prepare for callback
       
  1620 					// The requested number of words when the buffer was registered was 8, so simulate 10
       
  1621 					// to provoke an RxOverrun event.
       
  1622 					TInt numWords=10;
       
  1623 					// To support testing, any values of aId for StaticExtension must be shifted left one place
       
  1624 					// and for a Slave, the two msbs must be zero
       
  1625 					TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxWords;
       
  1626 					ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
       
  1627 					r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
       
  1628 					}
       
  1629 				}
       
  1630 			else
       
  1631 				{
       
  1632 				CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest ECtrlIoOvUndRunRxTx, iTestOverUnderState = 0x%x\n",iTestOverUnderState));
       
  1633 				r=KErrGeneral;
       
  1634 				}
       
  1635 			break;
       
  1636 			}
       
  1637 
       
  1638 		default:
       
  1639 			{
       
  1640 			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
       
  1641 			r=KErrArgument;
       
  1642 			break;
       
  1643 			}
       
  1644 		}
       
  1645 	return r;
       
  1646 	}
       
  1647