os/kernelhwsrv/kerneltest/e32test/iic/iic_psl/iic_slaveclient.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/iic/iic_psl/iic_slaveclient.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1647 @@
     1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32test/iic/iic_slaveclient.cpp
    1.18 +// Simulated client of IIC Platform Independent Layer (PIL) Slave functionality
    1.19 +//
    1.20 +
    1.21 +#include <kernel/kern_priv.h>		// for DThread, TDfc
    1.22 +#ifdef STANDALONE_CHANNEL
    1.23 +#include <drivers/iic_transaction.h>
    1.24 +#else
    1.25 +#include <drivers/iic.h>
    1.26 +#endif
    1.27 +#include "../t_iic.h"
    1.28 +
    1.29 +#ifdef STANDALONE_CHANNEL
    1.30 +#include <drivers/iic_channel.h>
    1.31 +#include "i2c.h"
    1.32 +#endif
    1.33 +#ifdef LOG_SLAVECLIENT
    1.34 +#define CLIENT_PRINT(str) Kern::Printf str
    1.35 +#else
    1.36 +#define CLIENT_PRINT(str)
    1.37 +#endif
    1.38 +
    1.39 +//For channel creation
    1.40 +#ifdef STANDALONE_CHANNEL
    1.41 +#define NUM_CHANNELS 3 // Arbitrary
    1.42 +
    1.43 +#if defined(MASTER_MODE) && !defined(SLAVE_MODE)
    1.44 +const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
    1.45 +#elif defined(MASTER_MODE) && defined(SLAVE_MODE)
    1.46 +const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
    1.47 +#else
    1.48 +const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
    1.49 +#endif
    1.50 +#define CHANNEL_TYPE(n) (KChannelTypeArray[n])
    1.51 +#define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex)
    1.52 +#define BUS_TYPE (DIicBusChannel::EI2c)
    1.53 +
    1.54 +#if defined(MASTER_MODE)
    1.55 +const TInt8 KI2cChannelNumBase = 10;	// Arbitrary, real platform may consult the Configuration Repository
    1.56 +										// Note limit of 5 bit representation (0-31)
    1.57 +
    1.58 +#else
    1.59 +const TInt8 KI2cChannelNumBase = 10 + NUM_CHANNELS;	// For Slave mode, want to provide different response
    1.60 +													// If client assumes Master mode, should be informed not available
    1.61 +#endif/*MASTER_MODE*/
    1.62 +
    1.63 +LOCAL_C TInt8 AssignChanNumI2c()
    1.64 +	{
    1.65 +	static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
    1.66 +	CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
    1.67 +	return iBaseChanNumI2c++; // Arbitrary, for illustration
    1.68 +	}
    1.69 +
    1.70 +class DIicSlaveClientChan : public DBase
    1.71 +	{
    1.72 +public:
    1.73 +	DIicSlaveClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TInt aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
    1.74 +	~DIicSlaveClientChan();
    1.75 +	TInt GetChanNum()const {return iChanNumber;};
    1.76 +	TInt GetChanType()const {return iChanType;};
    1.77 +	DIicBusChannel* GetChannelPtr(){return iChan;};
    1.78 +private:
    1.79 +	TInt8 iChanNumber;
    1.80 +	TInt iChanType;
    1.81 +	DIicBusChannel* iChan;
    1.82 +	};
    1.83 +
    1.84 +DIicSlaveClientChan::~DIicSlaveClientChan()
    1.85 +	{
    1.86 +	if(iChan)
    1.87 +		delete iChan;
    1.88 +	}
    1.89 +
    1.90 +#endif/*STANDALONE_CHANNEL*/
    1.91 +
    1.92 +const TInt KIicSlaveClientThreadPriority = 24;
    1.93 +
    1.94 +const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest
    1.95 +
    1.96 +const TInt KMaxNumChannels = 2;	// 1 "true" slave, one "dummy"
    1.97 +
    1.98 +#ifdef STANDALONE_CHANNEL
    1.99 +_LIT(KLddRootName,"iic_slaveclient_ctrless");
   1.100 +#else
   1.101 +_LIT(KLddRootName,"iic_slaveclient");
   1.102 +#endif
   1.103 +_LIT(KIicSlaveClientThreadName,"IicSlaveClientLddThread");
   1.104 +
   1.105 +
   1.106 +struct TCapsIicSlaveClient
   1.107 +    {
   1.108 +    TVersion version;
   1.109 +    };
   1.110 +
   1.111 +
   1.112 +class DDeviceIicSlaveClient : public DLogicalDevice
   1.113 +    {
   1.114 +    public:
   1.115 +    /**
   1.116 +     * The constructor
   1.117 +     */
   1.118 +    DDeviceIicSlaveClient();
   1.119 +    /**
   1.120 +     * The destructor
   1.121 +     */
   1.122 +    ~DDeviceIicSlaveClient();
   1.123 +    /**
   1.124 +     * Second stage constructor - install the device
   1.125 +     */
   1.126 +    virtual TInt Install();
   1.127 +    /**
   1.128 +     * Get the Capabilites of the device
   1.129 +     * @param aDes descriptor that will contain the returned capibilites
   1.130 +     */
   1.131 +    virtual void GetCaps(TDes8 &aDes) const;
   1.132 +    /**
   1.133 +     * Create a logical channel to the device
   1.134 +     */
   1.135 +    virtual TInt Create(DLogicalChannelBase*& aChannel);
   1.136 +    };
   1.137 +
   1.138 +
   1.139 +class DChannelIicSlaveClient : public DLogicalChannel
   1.140 +    {
   1.141 +    public:
   1.142 +    DChannelIicSlaveClient();
   1.143 +    ~DChannelIicSlaveClient();
   1.144 +
   1.145 +    virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
   1.146 +
   1.147 +	void RequestComplete(TInt r);
   1.148 +	TInt CheckDataWritten();
   1.149 +	TInt CheckDataRead();
   1.150 +
   1.151 +	static void SlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam);
   1.152 +#ifdef STANDALONE_CHANNEL
   1.153 +	static TInt OrderEntries(const DIicSlaveClientChan& aMatch, const DIicSlaveClientChan& aEntry);
   1.154 +#endif
   1.155 +    protected:
   1.156 +    virtual void HandleMsg(TMessageBase* aMsg);	// Note: this is a pure virtual in DLogicalChannel
   1.157 +
   1.158 +	TInt DoControl(TInt aId, TAny* a1, TAny* a2); // Name for convenience!
   1.159 +    TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); // Name for convenience!
   1.160 +
   1.161 +	private:
   1.162 +	TInt InitSlaveClient();
   1.163 +	TInt CbProcessOverUnderRunRxTx();
   1.164 +	TInt RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset);
   1.165 +	TInt SetNotificationTrigger(TInt aChannelId, TInt aTrigger);
   1.166 +	TInt StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2);
   1.167 +	TInt RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset);
   1.168 +	TInt CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch=NULL);
   1.169 +	TInt ReleaseChannel(TInt aChannelId);
   1.170 +	private:
   1.171 +	TDynamicDfcQue* iDfcQue;
   1.172 +	TIicBusSlaveCallback* iNotif;
   1.173 +
   1.174 +	HBuf8* iConfigHdr;
   1.175 +	TRequestStatus* iStatus;
   1.176 +
   1.177 +	TUint8* iRxBuf;
   1.178 +	TUint8* iTxBuf;
   1.179 +
   1.180 +	TUint8* iBusTxCheckBuf;
   1.181 +
   1.182 +	TInt8 iNumRegRxWords;
   1.183 +	TInt8 iNumRegTxWords;
   1.184 +
   1.185 +	TInt8 iTxRegGranularity;
   1.186 +	TInt8 iTxRegOffset;
   1.187 +	TInt8 iTxReqNumWords;
   1.188 +
   1.189 +	TInt8 iRxRegGranularity;
   1.190 +	TInt8 iRxRegOffset;
   1.191 +	TInt8 iRxReqNumWords;
   1.192 +
   1.193 +	TUint iBusId;
   1.194 +#ifdef STANDALONE_CHANNEL
   1.195 +	// For some slave-channel-only functions,e.g. ReleaseChannel, RegisterRxBuffer, etc.
   1.196 +	// the client needs to remember the slave channel that has been captured
   1.197 +	struct TCapturedChannel
   1.198 +		{
   1.199 +		DIicSlaveClientChan* iChannel;
   1.200 +		TInt iChannelId;
   1.201 +		};
   1.202 +	TCapturedChannel iCapturedChan;
   1.203 +#endif
   1.204 +	public:
   1.205 +	DThread* iClient;
   1.206 +	TInt iChannelId;	// public to be accessible by callback
   1.207 +	TInt* iClientChanId;
   1.208 +
   1.209 +	TInt iExpectedTrigger;
   1.210 +	TInt iFullDuplexReq;
   1.211 +	TInt iBlockedTrigger;
   1.212 +
   1.213 +	typedef enum TTestOverUnderState
   1.214 +		{
   1.215 +		EStartState  = 0x1,
   1.216 +		ERxOverrun_1,
   1.217 +		ERxOverrun_2,
   1.218 +		ETxUnderrun_1,
   1.219 +		ETxUnderrun_2
   1.220 +		};
   1.221 +	TTestOverUnderState iTestOverUnderState;
   1.222 +	};
   1.223 +
   1.224 +DDeviceIicSlaveClient::DDeviceIicSlaveClient()
   1.225 +// Constructor
   1.226 +    {
   1.227 +	CLIENT_PRINT(("> DDeviceIicSlaveClient::DDeviceIicSlaveClient()"));
   1.228 +    iParseMask=0;		// No info, no PDD, no Units
   1.229 +    iUnitsMask=0;
   1.230 +    iVersion=TVersion(KIicClientMajorVersionNumber,
   1.231 +		      KIicClientMinorVersionNumber,
   1.232 +		      KIicClientBuildVersionNumber);
   1.233 +    }
   1.234 +
   1.235 +#ifdef STANDALONE_CHANNEL
   1.236 +//Store all the channels created by the client into an array
   1.237 +RPointerArray<DIicSlaveClientChan> ChannelArray;
   1.238 +#endif
   1.239 +DDeviceIicSlaveClient::~DDeviceIicSlaveClient()
   1.240 +// Destructor
   1.241 +    {
   1.242 +	CLIENT_PRINT(("> DDeviceIicSlaveClient::~DDeviceIicSlaveClient()"));
   1.243 +#ifdef STANDALONE_CHANNEL
   1.244 +	//The client is reponsible for channel destroy in STANDALONE_CHANNEL mode
   1.245 +    ChannelArray.ResetAndDestroy();
   1.246 +#endif
   1.247 +	}
   1.248 +
   1.249 +TInt DDeviceIicSlaveClient::Install()
   1.250 +// Install the device driver.
   1.251 +    {
   1.252 +	CLIENT_PRINT(("> DDeviceIicSlaveClient::Install()"));
   1.253 +
   1.254 +    return(SetName(&KLddRootName));
   1.255 +    }
   1.256 +
   1.257 +
   1.258 +void DDeviceIicSlaveClient::GetCaps(TDes8& aDes) const
   1.259 +// Return the IicClient capabilities.
   1.260 +    {
   1.261 +	CLIENT_PRINT(("> DDeviceIicSlaveClient::GetCaps(TDes8& aDes) const"));
   1.262 +    TPckgBuf<TCapsIicSlaveClient> b;
   1.263 +    b().version=TVersion(KIicClientMajorVersionNumber,
   1.264 +			 KIicClientMinorVersionNumber,
   1.265 +			 KIicClientBuildVersionNumber);
   1.266 +    Kern::InfoCopy(aDes,b);
   1.267 +    }
   1.268 +
   1.269 +
   1.270 +TInt DDeviceIicSlaveClient::Create(DLogicalChannelBase*& aChannel)
   1.271 +// Create a channel on the device.
   1.272 +    {
   1.273 +	CLIENT_PRINT(("> DDeviceIicSlaveClient::Create(DLogicalChannelBase*& aChannel)"));
   1.274 +	if(iOpenChannels>=KMaxNumChannels)
   1.275 +		return KErrOverflow;
   1.276 +    aChannel=new DChannelIicSlaveClient;
   1.277 +    return aChannel?KErrNone:KErrNoMemory;
   1.278 +    }
   1.279 +
   1.280 +#ifdef STANDALONE_CHANNEL
   1.281 +//  auxiliary function for ordering entries in the array of channels
   1.282 +TInt DChannelIicSlaveClient::OrderEntries(const DIicSlaveClientChan& aMatch, const DIicSlaveClientChan& aEntry)
   1.283 +	{
   1.284 +	TUint8 l=(TUint8)aMatch.GetChanNum();
   1.285 +	TUint8 r=(TUint8)aEntry.GetChanNum();
   1.286 +	if(l>r)
   1.287 +		return -1;
   1.288 +	else if(l<r)
   1.289 +		return 1;
   1.290 +	else
   1.291 +		return 0;
   1.292 +	}
   1.293 +
   1.294 +// global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
   1.295 +TLinearOrder<DIicSlaveClientChan> EntryOrder(DChannelIicSlaveClient::OrderEntries);
   1.296 +
   1.297 +TInt GetChanPtr(const TInt aBusId, DIicSlaveClientChan*& aChan)
   1.298 +	{
   1.299 +    __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
   1.300 +	TInt32 chanId;
   1.301 +	chanId = GET_CHAN_NUM(aBusId);
   1.302 +    __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, chanId=0x%x\n",chanId));
   1.303 +	DIicSlaveClientChan chanEntry(NULL,(TInt8)chanId, DIicBusChannel::EMasterSlave);
   1.304 +
   1.305 +	TInt r = KErrNotFound;
   1.306 +	TInt aIndex = ChannelArray.FindInOrder(&chanEntry, EntryOrder);
   1.307 +
   1.308 +	if(aIndex >= 0)
   1.309 +		{
   1.310 +		aChan = ChannelArray[aIndex];
   1.311 +		r = KErrNone;
   1.312 +		}
   1.313 +
   1.314 +	return r;
   1.315 +	}
   1.316 +#endif/*STANDALONE_CHANNEL*/
   1.317 +
   1.318 +DECLARE_STANDARD_LDD()
   1.319 +	{
   1.320 +#ifdef STANDALONE_CHANNEL
   1.321 +	TInt r = KErrNone;
   1.322 +	DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
   1.323 +	DIicSlaveClientChan* aSlaveClientChan;
   1.324 +	for(TInt i=0; i<NUM_CHANNELS; i++)
   1.325 +			{
   1.326 +			CLIENT_PRINT(("\n"));
   1.327 +	#if defined(MASTER_MODE)
   1.328 +			if(CHANNEL_TYPE(i) == (DIicBusChannel::EMaster))
   1.329 +				{
   1.330 +				chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
   1.331 +				if(!chan)
   1.332 +					{
   1.333 +					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
   1.334 +					return NULL;
   1.335 +					}
   1.336 +				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
   1.337 +				if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
   1.338 +					{
   1.339 +					delete chan;
   1.340 +					return NULL;
   1.341 +					}
   1.342 +				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
   1.343 +				if(!aSlaveClientChan)
   1.344 +					{
   1.345 +					delete chan;
   1.346 +					return NULL;
   1.347 +					}
   1.348 +				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
   1.349 +				if(r!=KErrNone)
   1.350 +					{
   1.351 +					delete chan;
   1.352 +					delete aSlaveClientChan;
   1.353 +					break;
   1.354 +					}
   1.355 +				}
   1.356 +	#endif
   1.357 +	#if defined(MASTER_MODE) && defined(SLAVE_MODE)
   1.358 +			if(CHANNEL_TYPE(i) == DIicBusChannel::EMasterSlave)
   1.359 +				{
   1.360 +				chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
   1.361 +				if(!chanM)
   1.362 +					return NULL;
   1.363 +				chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
   1.364 +				if(!chanS)
   1.365 +					{
   1.366 +					delete chanM;
   1.367 +					return NULL;
   1.368 +					}
   1.369 +				chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
   1.370 +				if(!chan)
   1.371 +					{
   1.372 +					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
   1.373 +					delete chanM;
   1.374 +					delete chanS;
   1.375 +					return NULL;
   1.376 +					}
   1.377 +				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
   1.378 +				if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
   1.379 +					{
   1.380 +					delete chanM;
   1.381 +					delete chanS;
   1.382 +					delete chan;
   1.383 +					return NULL;
   1.384 +					}
   1.385 +				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
   1.386 +				if(!aSlaveClientChan)
   1.387 +					{
   1.388 +					delete chanM;
   1.389 +					delete chanS;
   1.390 +					delete chan;
   1.391 +					return NULL;
   1.392 +					}
   1.393 +				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
   1.394 +				if(r!=KErrNone)
   1.395 +					{
   1.396 +					delete chanM;
   1.397 +					delete chanS;
   1.398 +					delete chan;
   1.399 +					delete aSlaveClientChan;
   1.400 +					break;
   1.401 +					}
   1.402 +				}
   1.403 +	#endif
   1.404 +	#if defined(SLAVE_MODE)
   1.405 +			if(CHANNEL_TYPE(i) == (DIicBusChannel::ESlave))
   1.406 +				{
   1.407 +				chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE,CHANNEL_DUPLEX(i));
   1.408 +				if(!chan)
   1.409 +					{
   1.410 +					CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE(i),i));
   1.411 +					return NULL;
   1.412 +					}
   1.413 +				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
   1.414 +				if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
   1.415 +					return NULL;
   1.416 +				aSlaveClientChan = new DIicSlaveClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
   1.417 +				if(!aSlaveClientChan)
   1.418 +					{
   1.419 +					delete chan;
   1.420 +					return NULL;
   1.421 +					}
   1.422 +				r = ChannelArray.InsertInOrder(aSlaveClientChan,EntryOrder);
   1.423 +				if(r!=KErrNone)
   1.424 +					{
   1.425 +					delete chan;
   1.426 +					delete aSlaveClientChan;
   1.427 +					break;
   1.428 +					}
   1.429 +				}
   1.430 +	#endif
   1.431 +	#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
   1.432 +	#error I2C mode not defined as Master, Slave nor Master-Slave
   1.433 +	#endif
   1.434 +			}
   1.435 +#endif
   1.436 +	return new DDeviceIicSlaveClient;
   1.437 +	}
   1.438 +
   1.439 +
   1.440 +
   1.441 +DChannelIicSlaveClient::DChannelIicSlaveClient()
   1.442 +// Constructor
   1.443 +    {
   1.444 +	iFullDuplexReq=iBlockedTrigger=iExpectedTrigger=0;
   1.445 +	CLIENT_PRINT(("> DChannelIicSlaveClient::DChannelIicSlaveClient()"));
   1.446 +    iClient=&Kern::CurrentThread();
   1.447 +	// Increase the DThread's ref count so that it does not close without us
   1.448 +	iClient->Open();
   1.449 +	iTestOverUnderState = EStartState;
   1.450 +    }
   1.451 +
   1.452 +DChannelIicSlaveClient::~DChannelIicSlaveClient()
   1.453 +// Destructor
   1.454 +    {
   1.455 +	CLIENT_PRINT(("> DChannelIicSlaveClient::~DChannelIicSlaveClient()"));
   1.456 +	iDfcQue->Destroy();
   1.457 +	delete iNotif;
   1.458 +	delete iRxBuf;
   1.459 +	delete iTxBuf;
   1.460 +	delete iBusTxCheckBuf;
   1.461 +	// decrement the DThread's reference count
   1.462 +	Kern::SafeClose((DObject*&)iClient, NULL);
   1.463 +	}
   1.464 +
   1.465 +void DChannelIicSlaveClient::RequestComplete(TInt r)
   1.466 +	{
   1.467 +	Kern::RequestComplete(iClient, iStatus, r);
   1.468 +	}
   1.469 +
   1.470 +TInt DChannelIicSlaveClient::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
   1.471 +	{
   1.472 +	TInt r = KErrNone;
   1.473 +#ifdef STANDALONE_CHANNEL
   1.474 +	DIicSlaveClientChan* aChanPtr = NULL;
   1.475 +	if(iCapturedChan.iChannelId == aChannelId)
   1.476 +		aChanPtr = iCapturedChan.iChannel;
   1.477 +	if(!aChanPtr)
   1.478 +		return KErrArgument;
   1.479 +	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
   1.480 +		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->RegisterRxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
   1.481 +	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
   1.482 +		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->RegisterRxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
   1.483 +#else
   1.484 +	r = IicBus::RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
   1.485 +#endif
   1.486 +	return r;
   1.487 +	}
   1.488 +
   1.489 +TInt DChannelIicSlaveClient::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
   1.490 +	{
   1.491 +	TInt r = KErrNone;
   1.492 +#ifdef STANDALONE_CHANNEL
   1.493 +	DIicSlaveClientChan* aChanPtr = NULL;
   1.494 +	if(iCapturedChan.iChannelId == aChannelId)
   1.495 +		aChanPtr = iCapturedChan.iChannel;
   1.496 +	if(!aChanPtr)
   1.497 +		return KErrArgument;
   1.498 +	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
   1.499 +		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->SetNotificationTrigger(aTrigger);
   1.500 +	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
   1.501 +		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->SetNotificationTrigger(aTrigger);
   1.502 +#else
   1.503 +	r = IicBus::SetNotificationTrigger(aChannelId, aTrigger);
   1.504 +#endif
   1.505 +	return r;
   1.506 +	}
   1.507 +
   1.508 +TInt DChannelIicSlaveClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
   1.509 +	{
   1.510 +	TInt r = KErrNone;
   1.511 +#ifdef STANDALONE_CHANNEL
   1.512 +	DIicSlaveClientChan* aChanPtr;
   1.513 +	r = GetChanPtr(aId, aChanPtr);
   1.514 +	if(r != KErrNone)
   1.515 +		return r;
   1.516 +	if(!aChanPtr)
   1.517 +		return KErrArgument;
   1.518 +	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
   1.519 +		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->StaticExtension(aFunction, aParam1, aParam2);
   1.520 +	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
   1.521 +	r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->StaticExtension(aFunction, aParam1, aParam2);
   1.522 +#else
   1.523 +	r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
   1.524 +#endif
   1.525 +	return r;
   1.526 +	}
   1.527 +
   1.528 +TInt DChannelIicSlaveClient::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
   1.529 +	{
   1.530 +	TInt r = KErrNone;
   1.531 +#ifdef STANDALONE_CHANNEL
   1.532 +	DIicSlaveClientChan* aChanPtr = NULL;
   1.533 +	if(iCapturedChan.iChannelId == aChannelId)
   1.534 +		aChanPtr = iCapturedChan.iChannel;
   1.535 +	if(!aChanPtr)
   1.536 +		return KErrArgument;
   1.537 +	if(aChanPtr->GetChanType() == DIicBusChannel::EMasterSlave)
   1.538 +		r = ((DIicBusChannelMasterSlave*)(aChanPtr->GetChannelPtr()))->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset);
   1.539 +	else if(aChanPtr->GetChanType() == DIicBusChannel::ESlave)
   1.540 +		r = ((DIicBusChannelSlave*)(aChanPtr->GetChannelPtr()))->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset);
   1.541 +#else
   1.542 +	r = IicBus::RegisterTxBuffer(aChannelId, aTxBuffer, aBufGranularity, aNumWords, aOffset);
   1.543 +#endif
   1.544 +	return r;
   1.545 +	}
   1.546 +
   1.547 +TInt DChannelIicSlaveClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
   1.548 +	{
   1.549 +	TInt r = KErrNone;
   1.550 +#ifndef STANDALONE_CHANNEL
   1.551 +	r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
   1.552 +#else
   1.553 +	// Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
   1.554 +	if(!aCallback || !aConfigHdr)
   1.555 +		{
   1.556 +		return KErrArgument;
   1.557 +		}
   1.558 +
   1.559 +	// Get the channel
   1.560 +	DIicSlaveClientChan* chanPtr = NULL;
   1.561 +	if(r == KErrNone)
   1.562 +		{
   1.563 +		r = GetChanPtr(aBusId, chanPtr);
   1.564 +		if(r == KErrNone)
   1.565 +			{
   1.566 +			if(!chanPtr)
   1.567 +				{
   1.568 +				r = KErrArgument;
   1.569 +				}
   1.570 +			else
   1.571 +				{
   1.572 +				switch(chanPtr->GetChanType())
   1.573 +					{
   1.574 +					// CaptureChannel requests are only supported by channels in Slave mode.
   1.575 +					case DIicBusChannel::EMaster:
   1.576 +						{
   1.577 +						r = KErrNotSupported;
   1.578 +						break;
   1.579 +						}
   1.580 +					case DIicBusChannel::EMasterSlave:
   1.581 +						{
   1.582 +						r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
   1.583 +						break;
   1.584 +						}
   1.585 +					case DIicBusChannel::ESlave:
   1.586 +						{
   1.587 +						r = ((DIicBusChannelSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
   1.588 +						break;
   1.589 +						}
   1.590 +					default:
   1.591 +						{
   1.592 +						r = KErrArgument;
   1.593 +						}
   1.594 +					}
   1.595 +				// For synchronous capture, if successful then install the channel
   1.596 +				if(r == KErrNone)
   1.597 +					{
   1.598 +					if(!aAsynch)
   1.599 +						{
   1.600 +						 iCapturedChan.iChannel = chanPtr;
   1.601 +						 iCapturedChan.iChannelId = aChannelId;
   1.602 +						}
   1.603 +					else
   1.604 +						//For asynchronous capture, record slaveChanPtr, if later failed capture,
   1.605 +						//clean iCapturedChannel in client's callback.
   1.606 +						iCapturedChan.iChannel = chanPtr;
   1.607 +					}
   1.608 +				}
   1.609 +			}
   1.610 +		}
   1.611 +#endif
   1.612 +	return r;
   1.613 +	}
   1.614 +
   1.615 +TInt DChannelIicSlaveClient::ReleaseChannel(TInt aChannelId)
   1.616 +	{
   1.617 +	TInt r = KErrNone;
   1.618 +#ifndef STANDALONE_CHANNEL
   1.619 +	r = IicBus::ReleaseChannel(aChannelId);
   1.620 +#else
   1.621 +    __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicSlaveClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
   1.622 +    // Acquire the pointer to the Slave Channel
   1.623 +    if(iCapturedChan.iChannelId != aChannelId)
   1.624 +		return KErrNotFound;
   1.625 +
   1.626 +	if((iCapturedChan.iChannel)->GetChanType() == DIicBusChannel::EMasterSlave)
   1.627 +		r = ((DIicBusChannelMasterSlave*)((iCapturedChan.iChannel)->GetChannelPtr()))->ReleaseChannel();
   1.628 +	else if((iCapturedChan.iChannel)->GetChanType() == DIicBusChannel::ESlave)
   1.629 +		r = ((DIicBusChannelSlave*)((iCapturedChan.iChannel)->GetChannelPtr()))->ReleaseChannel();
   1.630 +	//After release channel, reset iCapturedChan
   1.631 +	iCapturedChan.iChannel = NULL;
   1.632 +	iCapturedChan.iChannelId = 0;
   1.633 +#endif
   1.634 +	return r;
   1.635 +	}
   1.636 +TInt DChannelIicSlaveClient::CbProcessOverUnderRunRxTx()
   1.637 +	{
   1.638 +	CLIENT_PRINT(("> DChannelIicSlaveClient::CbProcessOverUnderRunRxTx(), iTestOverUnderState=%d\n",iTestOverUnderState));
   1.639 +	TInt r = KErrNone;
   1.640 +	switch (iTestOverUnderState)
   1.641 +		{
   1.642 +		case(EStartState):
   1.643 +			{
   1.644 +			// In this state, no action is required
   1.645 +			break;
   1.646 +			};
   1.647 +		case(ERxOverrun_1):
   1.648 +			{
   1.649 +			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ERxOverrun_1\n"));
   1.650 +			// At this point, the outstanding request trigger should be ETxAllBytes | ETxUnderrun
   1.651 +			// and the flag to indicate duplex transfers should be cleared
   1.652 +			if((iExpectedTrigger != (ETxAllBytes | ETxUnderrun)) || (iFullDuplexReq != ETxAllBytes))
   1.653 +				{
   1.654 +				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
   1.655 +				r=KErrGeneral;
   1.656 +				}
   1.657 +			else
   1.658 +				{
   1.659 +				// Simulate providing a new buffer (actually, re-use existing buffer)
   1.660 +				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
   1.661 +				TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
   1.662 +				r = RegisterRxBuffer(iChannelId, rxPtr, iRxRegGranularity, iNumRegRxWords, iRxRegOffset);
   1.663 +
   1.664 +				if(r != KErrNone)
   1.665 +					{
   1.666 +					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterRxBuffer returned %d\n",r));
   1.667 +					}
   1.668 +				else
   1.669 +					{
   1.670 +					// For the next step, just specify the new Rx triggers (do not specify Tx triggers)
   1.671 +					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun));
   1.672 +					if(r != KErrNone)
   1.673 +						{
   1.674 +						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d\n",r));
   1.675 +						}
   1.676 +					else
   1.677 +						{
   1.678 +						iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
   1.679 +						iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
   1.680 +						iTestOverUnderState = ERxOverrun_2;	// Prepare for callback
   1.681 +						// The requested number of words when the buffer was registered was 8, so simulate 10
   1.682 +						// to provoke an RxOverrun event.
   1.683 +						TInt numWords=10;
   1.684 +						// To support testing, any values of aId for StaticExtension must be shifted left one place
   1.685 +						// and for a Slave, the two msbs must be zero
   1.686 +						TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxWords;
   1.687 +						ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
   1.688 +						r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
   1.689 +						}
   1.690 +					}
   1.691 +				}
   1.692 +			break;
   1.693 +			};
   1.694 +		case(ERxOverrun_2):
   1.695 +			{
   1.696 +			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ERxOverrun_2\n"));
   1.697 +			// At this point, the outstanding request trigger should be ETxAllBytes | ETxUnderrun
   1.698 +			// and the flag to indicate duplex transfers should be cleared
   1.699 +			if((iExpectedTrigger != (ETxAllBytes | ETxUnderrun)) || (iFullDuplexReq != ETxAllBytes))
   1.700 +				{
   1.701 +				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
   1.702 +				r=KErrGeneral;
   1.703 +				}
   1.704 +			else
   1.705 +				{
   1.706 +				// Simulate providing a new buffer (actually, re-use existing buffer)
   1.707 +				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
   1.708 +				TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
   1.709 +				r = RegisterRxBuffer(iChannelId, rxPtr, iRxRegGranularity, iNumRegRxWords, iRxRegOffset);
   1.710 +				if(r != KErrNone)
   1.711 +					{
   1.712 +					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterRxBuffer returned %d\n",r));
   1.713 +					}
   1.714 +				else
   1.715 +					{
   1.716 +					// Test that an attempt to modify existing Tx notification requests is rejected
   1.717 +					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxOverrun));
   1.718 +					if(r != KErrInUse)
   1.719 +						{
   1.720 +						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrInUse\n",r));
   1.721 +						}
   1.722 +					else
   1.723 +						{
   1.724 +						// For the next step, specify the new Rx triggers and the Tx triggers
   1.725 +						r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
   1.726 +						if(r != KErrNone)
   1.727 +							{
   1.728 +							CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrNone\n",r));
   1.729 +							}
   1.730 +						else
   1.731 +							{
   1.732 +							iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
   1.733 +							iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
   1.734 +							iTestOverUnderState = ETxUnderrun_1;	// Prepare for callback
   1.735 +							// The requested number of words when the buffer was registered was 12, so simulate 14
   1.736 +							// to provoke an TxUnderrun event.
   1.737 +							TInt numWords=14;
   1.738 +							// To support testing, any values of aId for StaticExtension must be shifted left one place
   1.739 +							// and for a Slave, the two msbs must be zero
   1.740 +							TInt ctrlIoVal = RBusDevIicClient::ECtrlIoTxWords;
   1.741 +							ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
   1.742 +							r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
   1.743 +							}
   1.744 +						}
   1.745 +					}
   1.746 +				}
   1.747 +			break;
   1.748 +			};
   1.749 +		case(ETxUnderrun_1):
   1.750 +			{
   1.751 +			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ETxOverrun_1\n"));
   1.752 +			// At this point, the outstanding request trigger should be ERxAllBytes | ERxOverrun
   1.753 +			// and the flag to indicate duplex transfers should be cleared
   1.754 +			if((iExpectedTrigger != (ERxAllBytes | ERxOverrun)) || (iFullDuplexReq != ERxAllBytes))
   1.755 +				{
   1.756 +				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
   1.757 +				r=KErrGeneral;
   1.758 +				}
   1.759 +			else
   1.760 +				{
   1.761 +				// Simulate providing a new buffer (actually, re-use existing buffer)
   1.762 +				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterTxBuffer\n"));
   1.763 +				TPtr8 rxPtr(iTxBuf,KTxBufSizeInBytes);
   1.764 +				r = RegisterTxBuffer(iChannelId, rxPtr, iTxRegGranularity, iNumRegTxWords, iTxRegOffset);
   1.765 +				if(r != KErrNone)
   1.766 +					{
   1.767 +					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterTxBuffer returned %d\n",r));
   1.768 +					}
   1.769 +				else
   1.770 +					{
   1.771 +					// For the next step, just specify the new Tx triggers (do not specify Rx triggers)
   1.772 +					r = SetNotificationTrigger(iChannelId, (ETxAllBytes | ETxUnderrun));
   1.773 +					if(r != KErrNone)
   1.774 +						{
   1.775 +						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d\n",r));
   1.776 +						}
   1.777 +					else
   1.778 +						{
   1.779 +						iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
   1.780 +						iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
   1.781 +						iTestOverUnderState = ETxUnderrun_2;	// Prepare for callback
   1.782 +						// The requested number of words when the buffer was registered was 12, so simulate 14
   1.783 +						// to provoke an TxUnderrun event.
   1.784 +						TInt numWords=14;
   1.785 +						// To support testing, any values of aId for StaticExtension must be shifted left one place
   1.786 +						// and for a Slave, the two msbs must be zero
   1.787 +						TInt ctrlIoVal = RBusDevIicClient::ECtrlIoTxWords;
   1.788 +						ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
   1.789 +						r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
   1.790 +						}
   1.791 +					}
   1.792 +				}
   1.793 +			break;
   1.794 +			};
   1.795 +		case(ETxUnderrun_2):
   1.796 +			{
   1.797 +			CLIENT_PRINT(("CbProcessOverUnderRunRxTx: entry state = ETxUnderrun_2\n"));
   1.798 +			// At this point, the outstanding request trigger should be ERxAllBytes | ERxOverrun
   1.799 +			// and the flag to indicate duplex transfers should be cleared
   1.800 +			if((iExpectedTrigger != (ERxAllBytes | ERxOverrun)) || (iFullDuplexReq != ERxAllBytes))
   1.801 +				{
   1.802 +				CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx, iExpectedTrigger=0x%x, iFullDuplexReq=%d\n",iExpectedTrigger,iFullDuplexReq));
   1.803 +				r=KErrGeneral;
   1.804 +				}
   1.805 +			else
   1.806 +				{
   1.807 +				// Simulate providing a new buffer (actually, re-use existing buffer)
   1.808 +				CLIENT_PRINT(("CbProcessOverUnderRunRxTx: invoking RegisterRxBuffer\n"));
   1.809 +				TPtr8 rxPtr(iTxBuf,KTxBufSizeInBytes);
   1.810 +				r = RegisterTxBuffer(iChannelId, rxPtr, iTxRegGranularity, iNumRegTxWords, iTxRegOffset);
   1.811 +				if(r != KErrNone)
   1.812 +					{
   1.813 +					CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - RegisterTxBuffer returned %d\n",r));
   1.814 +					}
   1.815 +				else
   1.816 +					{
   1.817 +					// Test that an attempt to modify existing Rx notification requests is rejected
   1.818 +					r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxUnderrun | ETxAllBytes | ETxUnderrun));
   1.819 +					if(r != KErrInUse)
   1.820 +						{
   1.821 +						CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrInUse\n",r));
   1.822 +						}
   1.823 +					else
   1.824 +						{
   1.825 +						// For the next step, specify the new Rx triggers and the Tx triggers
   1.826 +						r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
   1.827 +
   1.828 +						if(r != KErrNone)
   1.829 +							{
   1.830 +							CLIENT_PRINT(("Error: CbProcessOverUnderRunRxTx - SetNotificationTrigger returned %d, expected KErrNone\n",r));
   1.831 +							}
   1.832 +						else
   1.833 +							{
   1.834 +							// Simulate a simultaneous ERxAllBytes and ETxAllBytes event.
   1.835 +							iExpectedTrigger = ERxAllBytes | ETxAllBytes;
   1.836 +							iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
   1.837 +							iTestOverUnderState = EStartState;	// Prepare for callback - return to normal operation
   1.838 +							// Need to pass the number of words in an array, for use by StaticExtension
   1.839 +							TInt parms[2];
   1.840 +							parms[0]= 8;	// Number of Rx Words
   1.841 +							parms[1]=12;	// Number of Tx Words
   1.842 +							// To support testing, any values of aId for StaticExtension must be shifted left one place
   1.843 +							// and for a Slave, the two msbs must be zero
   1.844 +							TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxTxWords;
   1.845 +							ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
   1.846 +							r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)(&parms[0]));
   1.847 +							}
   1.848 +						}
   1.849 +					}
   1.850 +				}
   1.851 +			break;
   1.852 +			};
   1.853 +		default:
   1.854 +			{
   1.855 +			r = KErrGeneral;
   1.856 +			break;
   1.857 +			};
   1.858 +		}
   1.859 +	return r;
   1.860 +	}
   1.861 +
   1.862 +void DChannelIicSlaveClient::SlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam)
   1.863 +	{
   1.864 +	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));
   1.865 +	(void)aTxWords; // Unused if CLIENT_PRINT is undefined
   1.866 +	(void)aRxWords; // Unused if CLIENT_PRINT is undefined
   1.867 +	DChannelIicSlaveClient* channel = (DChannelIicSlaveClient*)aParam;
   1.868 +
   1.869 +	// Ensure only the valid bits of aTrigger are processed
   1.870 +	aTrigger &= 0xff;
   1.871 +
   1.872 +	CLIENT_PRINT(("SlaveClientCallbackFunc() - channel=0x%x\n",channel));
   1.873 +	if(aTrigger == EAsyncCaptChan)
   1.874 +		{
   1.875 +		CLIENT_PRINT(("SlaveClientCallbackFunc: capture channel completed\n"));
   1.876 +		// Set iChannelId, and write to user-side variable.
   1.877 +		channel->iChannelId=aChannelId;
   1.878 +		TInt r=Kern::ThreadRawWrite(channel->iClient,channel->iClientChanId,&aChannelId,sizeof(TInt));
   1.879 +		if(r == KErrNone)
   1.880 +			r=aReturn;
   1.881 +#ifdef STANDALONE_CHANNEL
   1.882 +		// Set the captured channel's iChannelId if the capture succeeds.
   1.883 +		if(r != KErrCompletion)
   1.884 +			(channel->iCapturedChan).iChannel = NULL;
   1.885 +		else
   1.886 +			(channel->iCapturedChan).iChannelId = aChannelId;
   1.887 +#endif/*STANDALONE_CHANNEL*/
   1.888 +	    channel->RequestComplete(r);	// Inform user of error
   1.889 +		return;
   1.890 +		}
   1.891 +	else
   1.892 +		{
   1.893 +		if(aTrigger&ERxAllBytes)
   1.894 +			{
   1.895 +			CLIENT_PRINT(("SlaveClientCallbackFunc() - ERxAllBytes\n"));
   1.896 +			aTrigger&= ~ERxAllBytes;
   1.897 +			channel->iExpectedTrigger&=~ERxAllBytes;
   1.898 +			channel->iFullDuplexReq&=~ERxAllBytes;
   1.899 +			aReturn=channel->CheckDataRead();
   1.900 +			// Check underrun
   1.901 +			if(aTrigger&ERxUnderrun)
   1.902 +				{
   1.903 +				if(channel->iExpectedTrigger&ERxUnderrun)
   1.904 +					{
   1.905 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxUnderrun found OK\n\n"));
   1.906 +					channel->iExpectedTrigger&=~ERxUnderrun;
   1.907 +					}
   1.908 +				else
   1.909 +					{
   1.910 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ERxUnderrun indicated\n\n"));
   1.911 +					aReturn = KErrGeneral;
   1.912 +					}
   1.913 +				}
   1.914 +			else
   1.915 +				{
   1.916 +				if(channel->iExpectedTrigger&ERxUnderrun)
   1.917 +					{
   1.918 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxUnderrun not (yet) seen\n\n"));
   1.919 +					aReturn = KErrGeneral;
   1.920 +					}
   1.921 +				}
   1.922 +			// Check overrun
   1.923 +			if(aTrigger&ERxOverrun)
   1.924 +				{
   1.925 +				if(channel->iExpectedTrigger&ERxOverrun)
   1.926 +					{
   1.927 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxOverrun found OK\n\n"));
   1.928 +					channel->iExpectedTrigger&=~ERxOverrun;
   1.929 +					}
   1.930 +				else
   1.931 +					{
   1.932 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ERxOverrun indicated\n\n"));
   1.933 +					aReturn = KErrGeneral;
   1.934 +					}
   1.935 +				}
   1.936 +			else
   1.937 +				{
   1.938 +				if(channel->iExpectedTrigger&ERxOverrun)
   1.939 +					{
   1.940 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ERxOverrun not (yet) seen\n\n"));
   1.941 +					aReturn = KErrGeneral;
   1.942 +					}
   1.943 +				}
   1.944 +			}
   1.945 +
   1.946 +		if(aTrigger&ETxAllBytes)
   1.947 +			{
   1.948 +			CLIENT_PRINT(("SlaveClientCallbackFunc() - ETxAllBytes\n"));
   1.949 +			aTrigger&= ~ETxAllBytes;
   1.950 +			channel->iExpectedTrigger&=~ETxAllBytes;
   1.951 +			channel->iFullDuplexReq&=~ETxAllBytes;
   1.952 +			aReturn=channel->CheckDataWritten();
   1.953 +			// Check underrun
   1.954 +			if(aTrigger&ETxUnderrun)
   1.955 +				{
   1.956 +				if(channel->iExpectedTrigger&ETxUnderrun)
   1.957 +					{
   1.958 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxUnderrun found OK\n\n"));
   1.959 +					channel->iExpectedTrigger&=~ETxUnderrun;
   1.960 +					}
   1.961 +				else
   1.962 +					{
   1.963 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ETxUnderrun indicated\n\n"));
   1.964 +					aReturn = KErrGeneral;
   1.965 +					}
   1.966 +				}
   1.967 +			else
   1.968 +				{
   1.969 +				if(channel->iExpectedTrigger&ETxUnderrun)
   1.970 +					{
   1.971 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxUnderrun not (yet) seen\n\n"));
   1.972 +					aReturn = KErrGeneral;
   1.973 +					}
   1.974 +				}
   1.975 +			// Check overrun
   1.976 +			if(aTrigger&ETxOverrun)
   1.977 +				{
   1.978 +				if(channel->iExpectedTrigger&ETxOverrun)
   1.979 +					{
   1.980 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxOverrun found OK\n\n"));
   1.981 +					channel->iExpectedTrigger&=~ETxOverrun;
   1.982 +					}
   1.983 +				else
   1.984 +					{
   1.985 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected ETxOverrun indicated\n\n"));
   1.986 +					aReturn = KErrGeneral;
   1.987 +					}
   1.988 +				}
   1.989 +			else
   1.990 +				{
   1.991 +				if(channel->iExpectedTrigger&ETxOverrun)
   1.992 +					{
   1.993 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - expected ETxOverrun not (yet) seen\n\n"));
   1.994 +					aReturn = KErrGeneral;
   1.995 +					}
   1.996 +				}
   1.997 +			}
   1.998 +
   1.999 +
  1.1000 +		if(aTrigger&EGeneralBusError)
  1.1001 +			{
  1.1002 +				if(channel->iExpectedTrigger&EGeneralBusError)
  1.1003 +					{
  1.1004 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc: EGeneralBusError - as expected\n\n"));
  1.1005 +					channel->iExpectedTrigger&=~EGeneralBusError;
  1.1006 +					if(aReturn == KErrGeneral)
  1.1007 +						{
  1.1008 +						aReturn=KErrNone; // If aReturn==KErrGeneral, set to KErrNone so t_iic knows test was successful
  1.1009 +						channel->iFullDuplexReq = 0; // The transaction is considered terminated, so don't wait for more triggers
  1.1010 +						}
  1.1011 +					else
  1.1012 +						{
  1.1013 +						CLIENT_PRINT(("\nSlaveClientCallbackFunc: aReturn not EGeneralBusError, =0x%x \n\n",aReturn));
  1.1014 +						aReturn=KErrGeneral;
  1.1015 +						}
  1.1016 +
  1.1017 +					}
  1.1018 +				else
  1.1019 +					{
  1.1020 +					CLIENT_PRINT(("\nSlaveClientCallbackFunc() - unexpected EGeneralBusError indicated\n\n"));
  1.1021 +					aReturn = KErrGeneral;
  1.1022 +					}
  1.1023 +			}
  1.1024 +
  1.1025 +		if((aTrigger < 0)||(aTrigger & (~0xFF)))
  1.1026 +			{
  1.1027 +			CLIENT_PRINT(("\nSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
  1.1028 +			}
  1.1029 +
  1.1030 +		// For simulataneous Rx,Tx triggers with ERxOverrun or TxUnderrun testing, need to call the following
  1.1031 +		if(aReturn == KErrNone)
  1.1032 +			{
  1.1033 +			aReturn = channel->CbProcessOverUnderRunRxTx();
  1.1034 +			}
  1.1035 +
  1.1036 +		if((channel->iExpectedTrigger == 0)&&(channel->iFullDuplexReq == 0))
  1.1037 +			channel->RequestComplete(aReturn);	// Complete user-side request only if all the triggers have been satisfied
  1.1038 +
  1.1039 +		} // if(aTrigger == EAsyncCaptChan)
  1.1040 +	}
  1.1041 +
  1.1042 +
  1.1043 +TInt DChannelIicSlaveClient::CheckDataRead()
  1.1044 +	{
  1.1045 +	TInt r=KErrNone;
  1.1046 +	// This channel will have provided a buffer for writing to, with a specified offset and number of words
  1.1047 +	// Bytes in the buffer before the offset should be set to zero
  1.1048 +	// Bytes written at and beyond the offset should exhibit an incrementing count
  1.1049 +	// Bytes beyond the offset that were not written to should be set to zero
  1.1050 +	TInt8 numWords=(iRxReqNumWords>iNumRegRxWords)?iNumRegRxWords:iRxReqNumWords;
  1.1051 +	TInt8 currVal=0;
  1.1052 +	TInt8 index = 0;
  1.1053 +	while(index<iRxRegOffset)
  1.1054 +		{
  1.1055 +		currVal=*(iRxBuf+index);
  1.1056 +		if(currVal != 0)
  1.1057 +			{
  1.1058 +			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0",index,currVal));
  1.1059 +			r=KErrCorrupt;
  1.1060 +			}
  1.1061 +		++index;
  1.1062 +		}
  1.1063 +
  1.1064 +	TInt8 checkVal=0x10; // first value written by simulated bus channel
  1.1065 +	TInt8 endOfData= (TInt8)(iRxRegOffset+(numWords*iRxRegGranularity));
  1.1066 +	TInt8 wordCount=0;
  1.1067 +	while(index<endOfData)
  1.1068 +		{
  1.1069 +		currVal = *(iRxBuf+index);
  1.1070 +		if(checkVal != currVal)
  1.1071 +			{
  1.1072 +			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0x%x",index,currVal,checkVal));
  1.1073 +			r=KErrCorrupt;
  1.1074 +			}
  1.1075 +		if(++wordCount == iRxRegGranularity)
  1.1076 +			{
  1.1077 +			wordCount=0;
  1.1078 +			checkVal++;
  1.1079 +			}
  1.1080 +		++index;
  1.1081 +		}
  1.1082 +
  1.1083 +	while(index<KRxBufSizeInBytes)
  1.1084 +		{
  1.1085 +		currVal=*(iRxBuf+index);
  1.1086 +		if(currVal != 0)
  1.1087 +			{
  1.1088 +			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataRead, index=%d, value =0x%x, expected 0",index,currVal);)
  1.1089 +			r=KErrCorrupt;
  1.1090 +			}
  1.1091 +		++index;
  1.1092 +		}
  1.1093 +	return r;
  1.1094 +	}
  1.1095 +
  1.1096 +
  1.1097 +TInt DChannelIicSlaveClient::CheckDataWritten()
  1.1098 +	{
  1.1099 +	TInt r=KErrNone;
  1.1100 +	// The pattern in the transmit buffer used by the simulated bus channel contains a incrementing count
  1.1101 +	// from 0 to (KTxBufSizeInBytes-1), therefore the first value to be present in the check buffer will be
  1.1102 +	// represented by the required offset.
  1.1103 +
  1.1104 +	// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
  1.1105 +	// Since the simulated bus channel is also in the kernel process it shares the same address space
  1.1106 +	// Get the address of the buffer
  1.1107 +	TUint testId = (((TUint)(RBusDevIicClient::ECtrlIoTxChkBuf))<<1)&0x3FFFFFFF;
  1.1108 +	CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten invoking StaticExtension ECtrlIoTxChkBuf with iBusId=0x%x, testId=0x%x, iBusTxCheckBuf=0x%x\n",iBusId,testId,iBusTxCheckBuf));
  1.1109 +	r = StaticExtension(iBusId, testId, &iBusTxCheckBuf, NULL);
  1.1110 +	if(r!=KErrNone)
  1.1111 +		{
  1.1112 +		CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten StaticExtension ECtrlIoTxChkBuf returned %d\n",r));
  1.1113 +		return r;
  1.1114 +		}
  1.1115 +
  1.1116 +	// Check that the values in the check buffer increment for the
  1.1117 +	// required number of words, and that any remaining bytes in the check buffer are set to zero.
  1.1118 +	TInt8 firstValue = iTxRegOffset;
  1.1119 +	TInt8 currVal = 0;
  1.1120 +	TInt8 wordsWritten = 0;
  1.1121 +	wordsWritten=(iTxReqNumWords>iNumRegTxWords)?iNumRegTxWords:iTxReqNumWords;
  1.1122 +	TInt8 index=0;
  1.1123 +	while(index<(wordsWritten*iTxRegGranularity))
  1.1124 +		{
  1.1125 +		currVal=*(iBusTxCheckBuf+index);
  1.1126 +		if(currVal != (TInt8)(firstValue+index))
  1.1127 +			{
  1.1128 +			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten, index=%d, value =0x%x, expected 0x%x",index,currVal,(TInt8)(firstValue+index)));
  1.1129 +			r=KErrCorrupt;
  1.1130 +			}
  1.1131 +		++index;
  1.1132 +		}
  1.1133 +	while(index<(iNumRegTxWords*iTxRegGranularity))
  1.1134 +		{
  1.1135 +		currVal=*(iBusTxCheckBuf+index);
  1.1136 +		if(currVal != 0)
  1.1137 +			{
  1.1138 +			CLIENT_PRINT(("DChannelIicSlaveClient::CheckDataWritten, index=%d, value =0x%x, expected 0",index,currVal));
  1.1139 +			r=KErrCorrupt;
  1.1140 +			}
  1.1141 +		++index;
  1.1142 +		}
  1.1143 +	return r;
  1.1144 +	}
  1.1145 +
  1.1146 +
  1.1147 +TInt DChannelIicSlaveClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
  1.1148 +	{
  1.1149 +	CLIENT_PRINT(("> DChannelIicSlaveClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
  1.1150 +
  1.1151 +	TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicSlaveClientThreadPriority,KIicSlaveClientThreadName);
  1.1152 +	if(r!=KErrNone)
  1.1153 +		return r;
  1.1154 +	SetDfcQ(iDfcQue);
  1.1155 +
  1.1156 +	// Allocate buffers for Rx, Tx operations
  1.1157 +	iRxBuf = new TUint8[KRxBufSizeInBytes];
  1.1158 +	iTxBuf = new TUint8[KTxBufSizeInBytes];
  1.1159 +	if((iRxBuf == NULL)||(iTxBuf == NULL))
  1.1160 +		return KErrNoMemory;
  1.1161 +	// Start receiving messages
  1.1162 +	iMsgQ.Receive();
  1.1163 +
  1.1164 +	return r;
  1.1165 +	}
  1.1166 +
  1.1167 +TInt DChannelIicSlaveClient::InitSlaveClient()
  1.1168 +	{
  1.1169 +	iNotif = new TIicBusSlaveCallback(DChannelIicSlaveClient::SlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
  1.1170 +	if(iNotif == NULL)
  1.1171 +		{
  1.1172 +		CLIENT_PRINT(("> DChannelIicSlaveClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
  1.1173 +		return KErrNoMemory;
  1.1174 +		}
  1.1175 +	return KErrNone;
  1.1176 +	}
  1.1177 +
  1.1178 +void DChannelIicSlaveClient::HandleMsg(TMessageBase* aMsg)
  1.1179 +	{
  1.1180 +    TThreadMessage& m=*(TThreadMessage*)aMsg;
  1.1181 +    TInt id=m.iValue;
  1.1182 +
  1.1183 +	CLIENT_PRINT((" >ldd: DChannelIicSlaveClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
  1.1184 +
  1.1185 +	if (id == (TInt)ECloseMsg)
  1.1186 +		{
  1.1187 +	    iMsgQ.iMessage->Complete(KErrNone,EFalse);
  1.1188 +		return;
  1.1189 +		}
  1.1190 +
  1.1191 +    if (id<0)
  1.1192 +		{
  1.1193 +		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
  1.1194 +		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
  1.1195 +		if (r!=KErrNone)
  1.1196 +			{
  1.1197 +	    	Kern::RequestComplete(iClient, pS, r);
  1.1198 +			}
  1.1199 +		m.Complete(KErrNone,ETrue);
  1.1200 +		}
  1.1201 +    else
  1.1202 +	if((id>=0)&&(id!=KMaxTInt))
  1.1203 +		{
  1.1204 +		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
  1.1205 +		m.Complete(r,ETrue);
  1.1206 +		}
  1.1207 +	}
  1.1208 +
  1.1209 +
  1.1210 +TInt DChannelIicSlaveClient::DoControl(TInt aId, TAny* a1, TAny* a2)
  1.1211 +	{
  1.1212 +	CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
  1.1213 +	TInt r=KErrNone;
  1.1214 +	// To support testing, any values of aId for StaticExtension must be shifted left one place
  1.1215 +	// and for a Slave, the two msbs must be zero
  1.1216 +	TInt ctrlIoVal = 0;
  1.1217 +	if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
  1.1218 +		ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
  1.1219 +
  1.1220 +	switch(aId)
  1.1221 +		{
  1.1222 +		case(RBusDevIicClient::EInitSlaveClient):
  1.1223 +			{
  1.1224 +			r=InitSlaveClient();
  1.1225 +			break;
  1.1226 +			}
  1.1227 +
  1.1228 +		case(RBusDevIicClient::ECaptureChanSync):
  1.1229 +			{
  1.1230 +			// a1 is a pointer to the TDes8* aConfigHdr
  1.1231 +			// a2 is a pointer to TInt* parms[2], where:
  1.1232 +			// parms[0]=(TInt*)aBusId;
  1.1233 +			// parms[1]=&aChannelId;
  1.1234 +			//
  1.1235 +			TInt* parms[2];
  1.1236 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
  1.1237 +			if(r!=KErrNone)
  1.1238 +				break;	// Can't proceed if can't access request parameters
  1.1239 +			//
  1.1240 +		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
  1.1241 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
  1.1242 +  			if (hdrSize<=0)
  1.1243 +				{
  1.1244 +				CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
  1.1245 + 				r = KErrArgument;
  1.1246 + 				break;
  1.1247 +				}
  1.1248 +			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
  1.1249 +				return KErrNoMemory;
  1.1250 +			r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
  1.1251 +			if(r!=KErrNone)
  1.1252 +				{
  1.1253 +				delete iConfigHdr;
  1.1254 +				break;
  1.1255 +				}
  1.1256 +			// Store the address of the user-side variable to update with the ChannelId
  1.1257 +			iClientChanId=parms[1];
  1.1258 +
  1.1259 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
  1.1260 +			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
  1.1261 +			if(r != KErrNone)
  1.1262 +			    {
  1.1263 +			    delete iConfigHdr;
  1.1264 +			    break;
  1.1265 +			    }
  1.1266 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
  1.1267 +
  1.1268 +			r = Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
  1.1269 +			if(r != KErrNone)
  1.1270 +				delete iConfigHdr;
  1.1271 +			break;
  1.1272 +			}
  1.1273 +
  1.1274 +		case(RBusDevIicClient::EReleaseChan):
  1.1275 +			{
  1.1276 +			// a1 represents TInt aChannelId
  1.1277 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
  1.1278 +			r = ReleaseChannel((TInt)a1);
  1.1279 +			delete iConfigHdr;
  1.1280 +			break;
  1.1281 +			}
  1.1282 +
  1.1283 +		case(RBusDevIicClient::ERegisterRxBuffer):
  1.1284 +			{
  1.1285 +			// a1 represents TInt aChannelId
  1.1286 +			// a2 represents (TAny*) of TInt8 parms[3] where parms[0]=aBufGranularity; parms[1]=aNumWords; parms[2]=aOffset
  1.1287 +			TInt8 parms[3];
  1.1288 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt8));
  1.1289 +			if(r!=KErrNone)
  1.1290 +				break;	// Can't proceed if can't access request parameters
  1.1291 +			// Store parameters for checking in the callback
  1.1292 +			iRxRegGranularity = parms[0];
  1.1293 +			iRxRegOffset= parms[2];
  1.1294 +			iNumRegRxWords=parms[1];
  1.1295 +
  1.1296 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking RegisterRxBuffer\n"));
  1.1297 +			TPtr8 rxPtr(iRxBuf,KRxBufSizeInBytes);
  1.1298 +			r = RegisterRxBuffer((TInt)a1, rxPtr, parms[0], parms[1], parms[2]);
  1.1299 +			break;
  1.1300 +			}
  1.1301 +
  1.1302 +		case(RBusDevIicClient::ERegisterTxBuffer):
  1.1303 +			{
  1.1304 +			// a1 represents TInt aChannelId
  1.1305 +			// a2 represents (TAny*) of TInt8 parms[3] where parms[0]=aBufGranularity; parms[1]=aNumWords; parms[2]=aOffset
  1.1306 +			TInt8 parms[3];
  1.1307 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt8));
  1.1308 +			if(r!=KErrNone)
  1.1309 +				break;	// Can't proceed if can't access request parameters
  1.1310 +			// Store parameters for checking in the callback
  1.1311 +			iTxRegGranularity = parms[0];
  1.1312 +			iTxRegOffset= parms[2];
  1.1313 +			iNumRegTxWords=parms[1];
  1.1314 +
  1.1315 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking RegisterTxBuffer\n"));
  1.1316 +			TPtr8 txPtr(iTxBuf,KTxBufSizeInBytes);
  1.1317 +			r = RegisterTxBuffer((TInt)a1, txPtr, parms[0], parms[1], parms[2]);
  1.1318 +			break;
  1.1319 +			}
  1.1320 +
  1.1321 +		case(RBusDevIicClient::ESetNotifTrigger):
  1.1322 +			{
  1.1323 +			// a1 represents (TAny*) of TRequestStatus* aStatus
  1.1324 +			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aTrigger
  1.1325 +			TInt parms[2];
  1.1326 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
  1.1327 +			if(r!=KErrNone)
  1.1328 +				break;	// Can't proceed if can't access request parameters
  1.1329 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking SetNotificationTrigger with aStatus=0x%x, aChannelId=0x%x, aTrigger=0x%x\n",a1,parms[0],parms[1]));
  1.1330 +			if(a1 == NULL)
  1.1331 +				{
  1.1332 +				r = KErrArgument;
  1.1333 +				break;
  1.1334 +				}
  1.1335 +			iStatus=(TRequestStatus*)a1;
  1.1336 +			// Set the flags for duplex processing
  1.1337 +			if((parms[1]&ERxAllBytes)&&(parms[1]&ETxAllBytes))
  1.1338 +				iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
  1.1339 +			r = SetNotificationTrigger(parms[0],parms[1]);
  1.1340 +			if(r == KErrTimedOut)
  1.1341 +				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
  1.1342 +			break;
  1.1343 +			}
  1.1344 +
  1.1345 +		case(RBusDevIicClient::ECtrlIoNotifNoTrigger):
  1.1346 +			{
  1.1347 +			// a1 represents (TAny*) of aChannelId
  1.1348 +			// a2 represents (TAny*) of aTrigger
  1.1349 +			TInt chanId = (TInt)a1;
  1.1350 +			TInt trigger = (TInt)a2;
  1.1351 +			// No TRequestStatus is accessed because the call to SetNotificationTrigger
  1.1352 +			// is either with zero (when it is valid to do so), or it is being called with a
  1.1353 +			// trigger value that is expected to be rejected.
  1.1354 +			r = SetNotificationTrigger(chanId,trigger);
  1.1355 +
  1.1356 +			if(r == KErrNone)
  1.1357 +				{
  1.1358 +				if((trigger&ERxAllBytes)&&(trigger&ETxAllBytes))
  1.1359 +					iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
  1.1360 +				}
  1.1361 +			if(r == KErrTimedOut)
  1.1362 +				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
  1.1363 +			break;
  1.1364 +			}
  1.1365 +
  1.1366 +		case(RBusDevIicClient::ECtrlIoRxWords):
  1.1367 +			{
  1.1368 +			// a1 represents TInt aBusId
  1.1369 +			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aNumWords
  1.1370 +			TInt parms[2];
  1.1371 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
  1.1372 +			if(r!=KErrNone)
  1.1373 +				break;	// Can't proceed if can't access request parameters
  1.1374 +			// Prepare iRxBuf
  1.1375 +			memset(iRxBuf,0,KRxBufSizeInBytes);
  1.1376 +			// Store the number of words for checking in the callback
  1.1377 +			iRxReqNumWords=(TInt8)(parms[1]);
  1.1378 +
  1.1379 +			TInt tempTrigger=0;
  1.1380 +			// Set the expected result
  1.1381 +			tempTrigger |= ERxAllBytes;
  1.1382 +			if(parms[1] < iNumRegRxWords)
  1.1383 +				tempTrigger |= ERxUnderrun;
  1.1384 +			if(parms[1] > iNumRegRxWords)
  1.1385 +				tempTrigger |= ERxOverrun;
  1.1386 +			if(iExpectedTrigger != EGeneralBusError)
  1.1387 +				iExpectedTrigger |= tempTrigger;
  1.1388 +			else
  1.1389 +				iBlockedTrigger |= tempTrigger;
  1.1390 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoRxWords) with aBusId=0x%x, aChannelId=0x%x, aNumBytes=0x%x\n",(TInt)a1,parms[0],parms[1]));
  1.1391 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(parms[1]));
  1.1392 +			if(r == KErrTimedOut)
  1.1393 +				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
  1.1394 +			break;
  1.1395 +			}
  1.1396 +
  1.1397 +		case(RBusDevIicClient::ECtrlIoTxWords):
  1.1398 +			{
  1.1399 +			// a1 represents TInt aBusId
  1.1400 +			// a2 represents (TAny*) of TInt parms[2] where parms[0]=aChannelId; parms[1]=aNumWords
  1.1401 +			TInt parms[2];
  1.1402 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt));
  1.1403 +			if(r!=KErrNone)
  1.1404 +				break;	// Can't proceed if can't access request parameters
  1.1405 +			// Prepare iTxBuf
  1.1406 +			TUint8* ptr=iTxBuf;
  1.1407 +			for(TInt offset=0; offset<KRxBufSizeInBytes; ++offset)
  1.1408 +				*ptr++=(TUint8)offset;
  1.1409 +			// Store the number of words for checking in the callback
  1.1410 +			iTxReqNumWords=(TInt8)(parms[1]);
  1.1411 +			TInt tempTrigger=0;
  1.1412 +			// Set the expected result
  1.1413 +			tempTrigger |= ETxAllBytes;
  1.1414 +			if(parms[1] < iNumRegTxWords)
  1.1415 +				tempTrigger |= ETxOverrun;
  1.1416 +			if(parms[1] > iNumRegTxWords)
  1.1417 +				tempTrigger |= ETxUnderrun;
  1.1418 +			if(iExpectedTrigger != EGeneralBusError)
  1.1419 +				iExpectedTrigger |= tempTrigger;
  1.1420 +			else
  1.1421 +				iBlockedTrigger |= tempTrigger;
  1.1422 +
  1.1423 +			// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
  1.1424 +			// Since the simulated bus channel is also in the kernel process it shares the same address space
  1.1425 +			// Get the address of the buffer
  1.1426 +			// As part of the callback invoked by IIC, this client will check the data stored by the simulated
  1.1427 +			// bus. Since the simulated bus channel is also in the kernel process it shares the same address space,
  1.1428 +			// so the buffer can be accessed directly - but the buffer is not created until it receives the following
  1.1429 +			// StaticExtension command, so the bus identifier represented by a1 is stored to allow accessing the buffer
  1.1430 +			// adddress from the callback.
  1.1431 +			iBusId=(TUint)a1;
  1.1432 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoTxWords) with aBusId=0x%x, aChannelId=0x%x, aNumBytes=0x%x\n",(TInt)a1,parms[0],parms[1]));
  1.1433 +			aId<<=1;
  1.1434 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(parms[1]));
  1.1435 +			break;
  1.1436 +			}
  1.1437 +
  1.1438 +		case(RBusDevIicClient::ECtrlIoRxTxWords):
  1.1439 +			{
  1.1440 +			// a1 represents TInt aBusId
  1.1441 +			// a2 represents (TAny*) of TInt parms[3] where parms[0]=aChannelId; parms[1]=aNumRxWords; parms[2]=aNumTxWords
  1.1442 +			TInt parms[3];
  1.1443 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),3*sizeof(TInt));
  1.1444 +			if(r!=KErrNone)
  1.1445 +				break;	// Can't proceed if can't access request parameters
  1.1446 +			// Prepare iRxBuf, iTxBuf
  1.1447 +			memset(iRxBuf,0,KRxBufSizeInBytes);
  1.1448 +			TUint8* ptr=iTxBuf;
  1.1449 +			for(TInt offset=0; offset<KRxBufSizeInBytes; ++offset)
  1.1450 +				*ptr++=(TUint8)offset;
  1.1451 +
  1.1452 +			// Store the number of words for checking in the callback
  1.1453 +			iRxReqNumWords=(TInt8)(parms[1]);
  1.1454 +			iTxReqNumWords=(TInt8)(parms[2]);
  1.1455 +
  1.1456 +			TInt tempTrigger=0;
  1.1457 +			// Set the expected result
  1.1458 +			tempTrigger |= (ERxAllBytes|ETxAllBytes);
  1.1459 +
  1.1460 +			if(parms[1] < iNumRegRxWords)
  1.1461 +				tempTrigger |= ERxUnderrun;
  1.1462 +			if(parms[1] > iNumRegRxWords)
  1.1463 +				tempTrigger |= ERxOverrun;
  1.1464 +
  1.1465 +			if(parms[2] < iNumRegTxWords)
  1.1466 +				tempTrigger |= ETxOverrun;
  1.1467 +			if(parms[2] > iNumRegTxWords)
  1.1468 +				tempTrigger |= ETxUnderrun;
  1.1469 +
  1.1470 +			if(iExpectedTrigger != EGeneralBusError)
  1.1471 +				iExpectedTrigger |= tempTrigger;
  1.1472 +			else
  1.1473 +				iBlockedTrigger |= tempTrigger;
  1.1474 +
  1.1475 +			// The bytes "transmitted" are stored in the simulated bus' iTxCheckBuf
  1.1476 +			// Since the simulated bus channel is also in the kernel process it shares the same address space
  1.1477 +			// Get the address of the buffer
  1.1478 +			// As part of the callback invoked by IIC, this client will check the data stored by the simulated
  1.1479 +			// bus. Since the simulated bus channel is also in the kernel process it shares the same address space,
  1.1480 +			// so the buffer can be accessed directly - but the buffer is not created until it receives the following
  1.1481 +			// StaticExtension command, so the bus identifier represented by a1 is stored to allow accessing the buffer
  1.1482 +			// adddress from the callback.
  1.1483 +			iBusId=(TUint)a1;
  1.1484 +
  1.1485 +			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]));
  1.1486 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)(parms[0]), (TAny*)(&(parms[1])));
  1.1487 +			if(r == KErrTimedOut)
  1.1488 +				r=KErrNone;	// KErrTimedOut is returned if the Client has not interacted with IIC for a while
  1.1489 +			break;
  1.1490 +			}
  1.1491 +
  1.1492 +		case(RBusDevIicClient::ECtlIoBusError):
  1.1493 +			{
  1.1494 +			// a1 represents TInt aBusId
  1.1495 +			// a2 represents TInt aChannelId
  1.1496 +			// Set the expected result
  1.1497 +			iExpectedTrigger |= EGeneralBusError;
  1.1498 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtlIoBusError) \n"));
  1.1499 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
  1.1500 +			break;
  1.1501 +			}
  1.1502 +
  1.1503 +		case(RBusDevIicClient::ECtrlIoUnblockNotification):
  1.1504 +			{
  1.1505 +			// a1 represents TInt aBusId
  1.1506 +			// a2 represents TInt aChannelId
  1.1507 +			iExpectedTrigger = iBlockedTrigger;
  1.1508 +			iBlockedTrigger=0;
  1.1509 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoUnblockNotification) \n"));
  1.1510 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
  1.1511 +			break;
  1.1512 +			}
  1.1513 +
  1.1514 +		case(RBusDevIicClient::ECtrlIoBlockNotification):
  1.1515 +			{
  1.1516 +			// a1 represents TInt aBusId
  1.1517 +			// a2 represents TInt aChannelId
  1.1518 +			iBlockedTrigger = iExpectedTrigger;
  1.1519 +			iExpectedTrigger = EGeneralBusError;	// For this test, just interested in if the timeout is detected
  1.1520 +													// iExpectedTrigger will be reinstated prior to unblocking
  1.1521 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoBlockNotification) \n"));
  1.1522 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, (TAny*)a2, NULL);
  1.1523 +			break;
  1.1524 +			}
  1.1525 +
  1.1526 +		case(RBusDevIicClient::ECtrlIoUpdTimeout):
  1.1527 +			{
  1.1528 +			// a1 represents TInt aBusId
  1.1529 +			// a2 represents TInt aChannelId
  1.1530 +
  1.1531 +			// For this test, instruct the simulated bus to do the following for the Master and Client timeout values:
  1.1532 +			// (1) Read the current timeout value and check that it is set to the default
  1.1533 +			// (2) Set it to different value
  1.1534 +			// (3) Read it back to check success
  1.1535 +			// (4) Return to the original value, and readback to confirm
  1.1536 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking StaticExtension (ECtrlIoBlockNotification) \n"));
  1.1537 +			r = StaticExtension((TUint)a1, (TUint)ctrlIoVal, NULL, NULL);
  1.1538 +			break;
  1.1539 +			}
  1.1540 +
  1.1541 +		default:
  1.1542 +			{
  1.1543 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl - unrecognised value for aId=0x%x\n",aId));
  1.1544 +			r=KErrArgument;
  1.1545 +			break;
  1.1546 +			}
  1.1547 +
  1.1548 +		}
  1.1549 +	return r;
  1.1550 +	}
  1.1551 +
  1.1552 +TInt DChannelIicSlaveClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
  1.1553 +	{
  1.1554 +	CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
  1.1555 +
  1.1556 +	TInt r=KErrNone;
  1.1557 +	switch(aId)
  1.1558 +		{
  1.1559 +		case(RBusDevIicClient::ECaptureChanAsync):
  1.1560 +			{
  1.1561 +			// a1 is a pointer to the TDes8* aConfigHdr
  1.1562 +			// a2 is a pointer to TInt* parms[2], where:
  1.1563 +			// parms[0]=(TInt*)aBusId;
  1.1564 +			// parms[1]=&aChannelId;
  1.1565 +			//
  1.1566 +			TInt* parms[2];
  1.1567 +			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
  1.1568 +			if(r!=KErrNone)
  1.1569 +				break;	// Can't proceed if can't access request parameters
  1.1570 +			//
  1.1571 +		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
  1.1572 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest hdrSize = 0x%x\n",hdrSize));
  1.1573 +  			if (hdrSize<=0)
  1.1574 +				{
  1.1575 +				CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest ERROR, hdrSize is invalid\n"));
  1.1576 + 				return KErrArgument;
  1.1577 +				}
  1.1578 +			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
  1.1579 +				return KErrNoMemory;
  1.1580 +			if((r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0))!=KErrNone)
  1.1581 +				{
  1.1582 +				delete iConfigHdr;
  1.1583 +				return r;
  1.1584 +				}
  1.1585 +			iStatus=aStatus;
  1.1586 +			// Store the address of the user-side variable to update with the ChannelId
  1.1587 +			iClientChanId=parms[1];
  1.1588 +			// Invoke the IIC API
  1.1589 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest invoking (asynchronous) CaptureChannel\n"));
  1.1590 +			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId, ETrue);
  1.1591 +			if(r != KErrNone)
  1.1592 +			    delete iConfigHdr;
  1.1593 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest (asynchronous) CaptureChannel returned %d\n",r));
  1.1594 +			break;
  1.1595 +			}
  1.1596 +
  1.1597 +		case(RBusDevIicClient::ECtrlIoOvUndRunRxTx):
  1.1598 +			{
  1.1599 +			iBusId = (TInt)a1;
  1.1600 +			iChannelId = (TInt)a2;
  1.1601 +			iStatus=aStatus;
  1.1602 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest status = 0x%x, busId = 0x%x, chanId =0x%x\n",iStatus,iBusId,iChannelId));
  1.1603 +
  1.1604 +			// This test is state-machine driven. It is instigated from this point, then subsequent steps
  1.1605 +			// are handled in the callback funciton SlaveClientCallbackFunc
  1.1606 +			//
  1.1607 +			// Check we in the appropriate state to start
  1.1608 +			if(iTestOverUnderState == EStartState)
  1.1609 +				{
  1.1610 +				// Re-use the previously-provided buffers. Just request the initial notification triggers,
  1.1611 +				// the simulate the first event (RxOverrun).
  1.1612 +				r = SetNotificationTrigger(iChannelId, (ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun));
  1.1613 +				if(r != KErrNone)
  1.1614 +					{
  1.1615 +					CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest SetNotificationTrigger returned %d\n",r));
  1.1616 +					}
  1.1617 +				else
  1.1618 +					{
  1.1619 +					// Trigger now set, so simulate the required event
  1.1620 +					iExpectedTrigger = ERxAllBytes | ERxOverrun | ETxAllBytes | ETxUnderrun;
  1.1621 +					iFullDuplexReq |= (ERxAllBytes|ETxAllBytes);
  1.1622 +					iTestOverUnderState = ERxOverrun_1;	// Prepare for callback
  1.1623 +					// The requested number of words when the buffer was registered was 8, so simulate 10
  1.1624 +					// to provoke an RxOverrun event.
  1.1625 +					TInt numWords=10;
  1.1626 +					// To support testing, any values of aId for StaticExtension must be shifted left one place
  1.1627 +					// and for a Slave, the two msbs must be zero
  1.1628 +					TInt ctrlIoVal = RBusDevIicClient::ECtrlIoRxWords;
  1.1629 +					ctrlIoVal = (ctrlIoVal << 1) & 0x3FFFFFFF;
  1.1630 +					r = StaticExtension(iBusId, ctrlIoVal, (TAny*)iChannelId, (TAny*)numWords);
  1.1631 +					}
  1.1632 +				}
  1.1633 +			else
  1.1634 +				{
  1.1635 +				CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest ECtrlIoOvUndRunRxTx, iTestOverUnderState = 0x%x\n",iTestOverUnderState));
  1.1636 +				r=KErrGeneral;
  1.1637 +				}
  1.1638 +			break;
  1.1639 +			}
  1.1640 +
  1.1641 +		default:
  1.1642 +			{
  1.1643 +			CLIENT_PRINT(("DChannelIicSlaveClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
  1.1644 +			r=KErrArgument;
  1.1645 +			break;
  1.1646 +			}
  1.1647 +		}
  1.1648 +	return r;
  1.1649 +	}
  1.1650 +