1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/iic/iic_psl/iic_client.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,2662 @@
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_client.cpp
1.18 +// Simulated (kernel-side) client of IIC Platform Independent Layer (PIL)
1.19 +//
1.20 +#include <kernel/kern_priv.h> // for DThread, TDfc
1.21 +#ifdef STANDALONE_CHANNEL
1.22 +#include <drivers/iic_transaction.h>
1.23 +#else
1.24 +#include <drivers/iic.h>
1.25 +#endif
1.26 +#include "../t_iic.h"
1.27 +#ifdef STANDALONE_CHANNEL
1.28 +#include <drivers/iic_channel.h>
1.29 +#include "i2c.h"
1.30 +#include "spi.h"
1.31 +#endif
1.32 +
1.33 +#ifdef LOG_CLIENT
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 +const TInt KIicClientThreadPriority = 24;
1.40 +const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest ... for MasterSlave functionality
1.41 +
1.42 +const TInt KMaxNumChannels = 3; // 1 SPI and 2 I2C
1.43 +
1.44 +// Define an array of channel that the client is going to create.
1.45 +// For iic_client, it needs SPI channels for Master tests, and I2c channels for MasterSlave tests.
1.46 +#ifdef STANDALONE_CHANNEL
1.47 +
1.48 +const TUint NUM_CHANNELS_SPI = 4; // Arbitrary
1.49 +const TInt KChannelTypeArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMaster};
1.50 +#define CHANNEL_TYPE_SPI(n) (KChannelTypeArraySpi[n])
1.51 +const DIicBusChannel::TChannelDuplex KChannelDuplexArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EFullDuplex};
1.52 +#define CHANNEL_DUPLEX_SPI(n) (KChannelDuplexArraySpi[n])
1.53 +#define BUS_TYPE_SPI (DIicBusChannel::ESpi)
1.54 +
1.55 +#define NUM_CHANNELS_I2C 3
1.56 +#if defined(MASTER_MODE) && !defined(SLAVE_MODE)
1.57 +const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
1.58 +#elif defined(MASTER_MODE) && defined(SLAVE_MODE)
1.59 +const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
1.60 +#else
1.61 +const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
1.62 +#endif
1.63 +#define CHANNEL_TYPE_I2C(n) (KChannelTypeArrayI2c[n])
1.64 +#define CHANNEL_DUPLEX_I2C(n) (DIicBusChannel::EHalfDuplex)
1.65 +#define BUS_TYPE_I2C (DIicBusChannel::EI2c)
1.66 +
1.67 +const TInt8 KSpiChannelNumBase = 1; // Arbitrary, real platform may consult the Configuration Repository
1.68 + // Note limit of 5 bit representation (0-31)
1.69 +
1.70 +LOCAL_C TInt8 AssignChanNumSpi()
1.71 + {
1.72 + static TInt8 iBaseChanNumSpi = KSpiChannelNumBase;
1.73 + CLIENT_PRINT(("SPI AssignChanNum - on entry, iBaseCanNum = 0x%x\n",iBaseChanNumSpi));
1.74 + return iBaseChanNumSpi++; // Arbitrary, for illustration
1.75 + }
1.76 +
1.77 +#if defined(MASTER_MODE)
1.78 +const TInt8 KI2cChannelNumBase = 10; // Arbitrary, real platform may consult the Configuration Repository
1.79 + // Note limit of 5 bit representation (0-31)
1.80 +
1.81 +#else
1.82 +const TInt8 KI2cChannelNumBase = 10 + NUM_CHANNELS; // For Slave mode, want to provide different response
1.83 + // If client assumes Master mode, should be informed not available
1.84 +#endif
1.85 +
1.86 +LOCAL_C TInt8 AssignChanNumI2c()
1.87 + {
1.88 + static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
1.89 + CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
1.90 + return iBaseChanNumI2c++; // Arbitrary, for illustration
1.91 + }
1.92 +
1.93 +class DIicClientChan : public DBase
1.94 + {
1.95 +public:
1.96 + DIicClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TUint8 aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
1.97 + ~DIicClientChan();
1.98 + TInt GetChanNum()const {return iChanNumber;};
1.99 + TUint8 GetChanType()const {return iChanType;};
1.100 + DIicBusChannel* GetChannelPtr(){return iChan;};
1.101 + inline DIicClientChan& operator=(DIicClientChan& aChan) {iChanNumber=aChan.iChanNumber; iChanType=aChan.iChanType; iChan=aChan.iChan; return *this;};
1.102 + inline TInt operator==(DIicClientChan& aChan) {if((iChanNumber == aChan.iChanNumber)&&(iChanType == aChan.iChanType)&&(iChan == aChan.iChan)) return 1;return 0;};
1.103 +private:
1.104 + TInt iChanNumber;
1.105 + TUint8 iChanType;
1.106 + DIicBusChannel* iChan;
1.107 + };
1.108 +
1.109 +DIicClientChan::~DIicClientChan()
1.110 + {
1.111 + delete iChan;
1.112 + }
1.113 +
1.114 +#endif /*STANDALONE_CHANNEL*/
1.115 +
1.116 +
1.117 +#ifdef STANDALONE_CHANNEL
1.118 +_LIT(KLddRootName,"iic_client_ctrless");
1.119 +#else
1.120 +_LIT(KLddRootName,"iic_client");
1.121 +#endif
1.122 +_LIT(KIicClientThreadName,"IicClientLddThread");
1.123 +
1.124 +struct TCapsIicClient
1.125 + {
1.126 + TVersion version;
1.127 + };
1.128 +
1.129 +struct TTransStatusPair
1.130 + {
1.131 + TRequestStatus* iReq;
1.132 + TIicBusTransaction* iTrans;
1.133 + };
1.134 +
1.135 +struct TTransCbPair
1.136 + {
1.137 + TIicBusTransaction* iTrans;
1.138 + TIicBusCallback* iCb;
1.139 + };
1.140 +
1.141 +struct TExtractInfo
1.142 + {
1.143 + TExtractInfo(){iBufPtr = NULL; iTfer = NULL;}
1.144 + ~TExtractInfo(){delete iBufPtr; delete iTfer;}
1.145 + TDes8* iBufPtr;
1.146 + TIicBusTransfer* iTfer;
1.147 + TIicBusTransaction* iTrans;
1.148 + };
1.149 +
1.150 +struct TTransBufReuseData
1.151 + {
1.152 + // Convenience for testing, only - retain pointers to private data
1.153 + // so that it can be re-used from a callback.
1.154 + TIicBusTransaction* iTransaction;
1.155 + TIicBusTransfer* iHdTfer;
1.156 + TIicBusTransfer* iFdTfer;
1.157 + TDes8* iHdr;
1.158 + // Pointer to callback object (for cleanup)
1.159 + TIicBusCallback* iCallback;
1.160 + };
1.161 +
1.162 +class DDeviceIicClient : public DLogicalDevice
1.163 + {
1.164 + public:
1.165 + /**
1.166 + * The constructor
1.167 + */
1.168 + DDeviceIicClient();
1.169 + /**
1.170 + * The destructor
1.171 + */
1.172 + ~DDeviceIicClient();
1.173 + /**
1.174 + * Second stage constructor - install the device
1.175 + */
1.176 + virtual TInt Install();
1.177 + /**
1.178 + * Get the Capabilites of the device
1.179 + * @param aDes descriptor that will contain the returned capibilites
1.180 + */
1.181 + virtual void GetCaps(TDes8 &aDes) const;
1.182 + /**
1.183 + * Create a logical channel to the device
1.184 + */
1.185 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.186 +
1.187 + public:
1.188 + };
1.189 +
1.190 +#ifdef STANDALONE_CHANNEL
1.191 +/*This class is used to test the set and get inline functions
1.192 + * of DIicBusChannel Interface.
1.193 + * */
1.194 +class TTestIicChannelInterface: public DIicBusChannel
1.195 +{
1.196 +public:
1.197 + TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex);
1.198 + ~TTestIicChannelInterface(){};
1.199 + TInt DoCreate(){return 0;};
1.200 + TInt CheckHdr(TDes8* /*aHdr*/){return 0;};
1.201 + TInt TestInterface();
1.202 +private:
1.203 + TBool TestChannelType(DIicBusChannel::TChannelType aType );
1.204 + TBool TestBusType(DIicBusChannel::TBusType aType );
1.205 + TBool TestDuplexType(DIicBusChannel::TChannelDuplex aType );
1.206 +};
1.207 +
1.208 +TTestIicChannelInterface::TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex)
1.209 + : DIicBusChannel(aChannelType, aBusType, aChanDuplex)
1.210 + {}
1.211 +
1.212 +TBool TTestIicChannelInterface::TestChannelType(DIicBusChannel::TChannelType aType)
1.213 + {
1.214 + CLIENT_PRINT(("Setting channel type 0x%x\n", aType));
1.215 + SetChannelType(aType);
1.216 + if(aType != ChannelType())
1.217 + {
1.218 + CLIENT_PRINT(("ERROR: Mismatch, looking for channel 0x%x but found 0x%x\n", aType, ChannelType()));
1.219 + return EFalse;
1.220 + }
1.221 + else
1.222 + {
1.223 + CLIENT_PRINT(("Looking for channel 0x%x and found 0x%x\n", aType, ChannelType()));
1.224 + }
1.225 + return ETrue;
1.226 + }
1.227 +
1.228 +TBool TTestIicChannelInterface::TestBusType(DIicBusChannel::TBusType aType)
1.229 + {
1.230 + CLIENT_PRINT(("Setting Bus type 0x%x\n", aType));
1.231 + SetBusType(aType);
1.232 + if(aType != BusType())
1.233 + {
1.234 + CLIENT_PRINT(("ERROR: Mismatch, looking for Bus 0x%x but found 0x%x\n", aType, BusType()));
1.235 + return EFalse;
1.236 + }
1.237 + else
1.238 + {
1.239 + CLIENT_PRINT(("Looking for Bus 0x%x and found 0x%x\n", aType, BusType()));
1.240 + }
1.241 + return ETrue;
1.242 + }
1.243 +
1.244 +TBool TTestIicChannelInterface::TestDuplexType(DIicBusChannel::TChannelDuplex aType)
1.245 + {
1.246 + CLIENT_PRINT(("Setting duplex channel type 0x%x\n", aType));
1.247 + SetChannelType(aType);
1.248 + if(aType != ChannelDuplex())
1.249 + {
1.250 + CLIENT_PRINT(("ERROR: Mismatch, looking for duplex channel 0x%x but found 0x%x\n", aType, ChannelDuplex()));
1.251 + return EFalse;
1.252 + }
1.253 + else
1.254 + {
1.255 + CLIENT_PRINT(("Looking for Duplex Channel 0x%x and found 0x%x\n", aType, ChannelDuplex()));
1.256 + }
1.257 + return ETrue;
1.258 + }
1.259 +
1.260 +TInt TTestIicChannelInterface::TestInterface()
1.261 + {
1.262 +
1.263 + RArray <DIicBusChannel::TChannelType> chtype;
1.264 + RArray <DIicBusChannel::TBusType> bustype;
1.265 + RArray <DIicBusChannel::TChannelDuplex> dutype;
1.266 +
1.267 + chtype.Append(DIicBusChannel::EMaster);
1.268 + chtype.Append(DIicBusChannel::ESlave);
1.269 + chtype.Append(DIicBusChannel::EMasterSlave);
1.270 +
1.271 + bustype.Append(DIicBusChannel::EI2c);
1.272 + bustype.Append(DIicBusChannel::ESpi);
1.273 + bustype.Append(DIicBusChannel::EMicrowire);
1.274 + bustype.Append(DIicBusChannel::ECci);
1.275 + bustype.Append(DIicBusChannel::ESccb);
1.276 +
1.277 + dutype.Append(DIicBusChannel::EHalfDuplex);
1.278 + dutype.Append(DIicBusChannel::EFullDuplex);
1.279 +
1.280 + int result = KErrNone;
1.281 + int count = chtype.Count();
1.282 + int i=0;
1.283 +
1.284 + CLIENT_PRINT(("\nCheck Master/Slave channel setting\n"));
1.285 + CLIENT_PRINT(("\nChannel MASK = 0x%x\n", KChannelTypeMask));
1.286 + for(i=0; i< count; ++i)
1.287 + {
1.288 + if(!TestChannelType(chtype[i]))
1.289 + {
1.290 + result = KErrGeneral;
1.291 + break;
1.292 + }
1.293 + }
1.294 + CLIENT_PRINT(("\nCheck Master/Slave channel setting from higher bit number to lower, reverse enum.\n"));
1.295 + for(i=count-1; i >= 0; --i)
1.296 + {
1.297 + if(!TestChannelType(chtype[i]))
1.298 + {
1.299 + result = KErrGeneral;
1.300 + break;
1.301 + }
1.302 + }
1.303 +
1.304 + CLIENT_PRINT(("\nCheck Channel Bus type settings\n"));
1.305 + CLIENT_PRINT(("\nBus MASK = 0x%x\n", KBusTypeMask));
1.306 + count = bustype.Count();
1.307 + for(i=0; i< count; ++i)
1.308 + {
1.309 + if(!TestBusType(bustype[i]))
1.310 + {
1.311 + result = KErrGeneral;
1.312 + break;
1.313 + }
1.314 + }
1.315 + CLIENT_PRINT(("\nCheck Channel Bus type settings from higher bit number to lower, reverse enum.\n"));
1.316 + for(i = count-1; i >= 0; --i)
1.317 + {
1.318 + if(!TestBusType(bustype[i]))
1.319 + {
1.320 + result = KErrGeneral;
1.321 + break;
1.322 + }
1.323 + }
1.324 + CLIENT_PRINT(("\nCheck Channel Duplex settings\n"));
1.325 + CLIENT_PRINT(("\nDuplex MASK = 0x%x\n", KChannelDuplexMask));
1.326 + count = dutype.Count();
1.327 + for(i=0; i < count; ++i)
1.328 + {
1.329 + if(!TestDuplexType(dutype[i]))
1.330 + {
1.331 + result = KErrGeneral;
1.332 + break;
1.333 + }
1.334 + }
1.335 + CLIENT_PRINT(("\nCheck Channel Duplex setting from higher bit number to lower, reverse enum.\n"));
1.336 + for(i = count-1; i >= 0; --i)
1.337 + {
1.338 + if(!TestDuplexType(dutype[i]))
1.339 + {
1.340 + result = KErrGeneral;
1.341 + break;
1.342 + }
1.343 + }
1.344 + chtype.Close();
1.345 + dutype.Close();
1.346 + bustype.Close();
1.347 + return result;
1.348 + }
1.349 +#endif //STANDALONE_CHANNEL
1.350 +
1.351 +class DChannelIicClient : public DLogicalChannel
1.352 + {
1.353 + public:
1.354 + DChannelIicClient();
1.355 + ~DChannelIicClient();
1.356 +
1.357 + TInt CleanupExtractTrans(TIicBusTransaction *aTrans);
1.358 +
1.359 + TInt InitIicClient();
1.360 +
1.361 + virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
1.362 +
1.363 + protected:
1.364 + virtual void HandleMsg(TMessageBase* aMsg); // Note: this is a pure virtual in DLogicalChannel
1.365 +
1.366 + void DoCancel(TInt aMask); // Name for convenience!
1.367 + TInt DoControl(TInt aId, TAny* a1, TAny* a2); // Name for convenience!
1.368 + TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); // Name for convenience!
1.369 +
1.370 + void TestTransModification(TIicBusTransaction* aTransaction, // public to be accessed by callback
1.371 + TIicBusTransfer* aHdTfer,
1.372 + TIicBusTransfer* aFdTfer,
1.373 + TDes8* aHdr);
1.374 +#ifdef STANDALONE_CHANNEL
1.375 + public:
1.376 + static TInt OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry);
1.377 +#endif
1.378 + private:
1.379 + TInt ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans);
1.380 + TInt CreateTransferListHalfDuplex(
1.381 + TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1.382 + TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1.383 + TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
1.384 + TInt CreateTransferListFullDuplex(
1.385 + TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1.386 + TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1.387 + TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
1.388 +
1.389 +
1.390 + TInt DeleteFullDuplexTest(TIicBusTransaction *aTrans);
1.391 +
1.392 + TInt DoCreateFullDuplexTransTest(TInt aTestType);
1.393 +
1.394 + TInt DoPriorityTest(TInt aBusId);
1.395 + TInt ConstructTransactionOne(TIicBusTransaction*& aTrans);
1.396 + void CleanupTransactionOne(TIicBusTransaction*& aTrans);
1.397 +
1.398 +
1.399 + TInt InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair);
1.400 +
1.401 + TInt CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf);
1.402 +
1.403 + //Add new functions for controller-less mode
1.404 + TInt QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback=NULL);
1.405 + TInt CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction);
1.406 + TInt StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2);
1.407 + TInt CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch=NULL);
1.408 + TInt ReleaseChannel(TInt aChannelId);
1.409 + public:
1.410 + inline void Lock() {Kern::MutexWait(*iArrayMutex);}
1.411 + inline void Unlock() {Kern::MutexSignal(*iArrayMutex);}
1.412 + inline void GetWriteAccess() {Kern::SemaphoreWait(*iChanArrWrtSem);} // aNTicks not specified = wait forever
1.413 + inline void FreeWriteAccess() {Kern::SemaphoreSignal(*iChanArrWrtSem);}
1.414 +
1.415 + void CleanupTransaction(TIicBusTransaction*& aTrans); // public for access by callback
1.416 +
1.417 + static TIicBusTransaction* MultiTranscCallbackFunc(TIicBusTransaction* aTrans, TAny* aParam);
1.418 +
1.419 + static void TransModifCallback(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam);
1.420 +
1.421 + private:
1.422 + TDynamicDfcQue* iDfcQue;
1.423 +
1.424 + DMutex* iArrayMutex; // used to protect array of channels
1.425 + DSemaphore* iChanArrWrtSem; // used to synchronise write access to iChannelArray
1.426 +
1.427 + // Used for Transaction One
1.428 + HBuf8* buf1;
1.429 + HBuf8* buf2;
1.430 + HBuf8* buf3;
1.431 + HBuf8* buf4;
1.432 + HBuf8* buf5;
1.433 + HBuf8* buf6;
1.434 + TIicBusTransfer* tfer1;
1.435 + TIicBusTransfer* tfer2;
1.436 + TIicBusTransfer* tfer3;
1.437 + TIicBusTransfer* tfer4;
1.438 + TIicBusTransfer* tfer5;
1.439 + TIicBusTransfer* tfer6;
1.440 + TIicBusTransfer* tfer7;
1.441 + HBuf8* header;
1.442 + HBuf8* header2;
1.443 + HBuf8* header3;
1.444 + HBuf8* header4;
1.445 + HBuf8* header5;
1.446 + HBuf8* headerBlock;
1.447 + TConfigSpiBufV01* spiHeader;
1.448 +
1.449 +
1.450 + static TIicBusTransaction* iMultiTransac;
1.451 +
1.452 + // Used for simple transactions
1.453 + TIicBusTransaction* iTrans;
1.454 + TConfigSpiBufV01* iSpiBuf;
1.455 + TConfigI2cBufV01* iI2cBuf;
1.456 + TIicBusTransfer* iTfer;
1.457 + TIicBusTransactionPreamble* iTransPreamble;
1.458 + TIicBusTransfer* iFdTfer;
1.459 +
1.460 + public:
1.461 + DThread* iClient;
1.462 + RPointerArray<TTransStatusPair> iTransStatArrayByTrans;
1.463 + RPointerArray<TTransStatusPair> iTransStatArrayByStatus;
1.464 + RPointerArray<TTransCbPair> iTransCbArrayByTrans;
1.465 + RPointerArray<TExtractInfo> iExtractInfoArray;
1.466 +
1.467 + // Support for Preamble testing
1.468 + TRequestStatus* iPreambleStatus;
1.469 + TRequestStatus* iMultiTranscStatus;
1.470 +
1.471 + // Support for buffer re-use testing
1.472 + TTransBufReuseData iTransBufReuseData;
1.473 +
1.474 + // Support for MasterSlave processing
1.475 + private:
1.476 + TInt InitSlaveClient();
1.477 +
1.478 + private:
1.479 + HBuf8* iConfigHdr;
1.480 + TRequestStatus* iStatus;
1.481 +
1.482 + public:
1.483 + void RequestComplete(TInt r);
1.484 +
1.485 + public:
1.486 + TIicBusSlaveCallback* iNotif; // public to be accessible by callback
1.487 + TInt iChannelId; // public to be accessible by callback
1.488 + TInt* iClientChanId;
1.489 +
1.490 +#ifdef STANDALONE_CHANNEL
1.491 + //Used to store the captured channel
1.492 + struct TCapturedChannel
1.493 + {
1.494 + DIicClientChan* iChanPtr;
1.495 + TInt iChannelId;
1.496 + };
1.497 + TCapturedChannel iCapturedChannel;
1.498 +#endif
1.499 + };
1.500 +
1.501 +DDeviceIicClient::DDeviceIicClient()
1.502 +// Constructor
1.503 + {
1.504 + CLIENT_PRINT(("> DDeviceIicClient::DDeviceIicClient()"));
1.505 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::DDeviceIicClient()"));
1.506 + iParseMask=0; // No info, no PDD, no Units
1.507 + iUnitsMask=0;
1.508 + iVersion=TVersion(KIicClientMajorVersionNumber,
1.509 + KIicClientMinorVersionNumber,
1.510 + KIicClientBuildVersionNumber);
1.511 + }
1.512 +#ifdef STANDALONE_CHANNEL
1.513 +// auxiliary function for ordering entries in the array of channels
1.514 +TInt DChannelIicClient::OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry)
1.515 + {
1.516 + TUint8 l=(TUint8)aMatch.GetChanNum();
1.517 + TUint8 r=(TUint8)aEntry.GetChanNum();
1.518 + if(l<r)
1.519 + return -1;
1.520 + else if(l>r)
1.521 + return 1;
1.522 + else
1.523 + return 0;
1.524 + }
1.525 +// global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
1.526 +TLinearOrder<DIicClientChan> EntryOrder(DChannelIicClient::OrderEntries);
1.527 +
1.528 +// Store all the channels created by the client
1.529 +RPointerArray<DIicClientChan> ChannelArray;
1.530 +#endif /*STANDALONE_CHANNEL*/
1.531 +
1.532 +DDeviceIicClient::~DDeviceIicClient()
1.533 + {
1.534 + CLIENT_PRINT(("> DDeviceIicClient::~DDeviceIicClient()"));
1.535 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::~DDeviceIicClient()"));
1.536 +#ifdef STANDALONE_CHANNEL
1.537 + //For Standalone Channel, the client is responsible for channel destroy
1.538 + ChannelArray.ResetAndDestroy();
1.539 +#endif
1.540 + }
1.541 +
1.542 +TInt DDeviceIicClient::Install()
1.543 +// Install the device driver.
1.544 + {
1.545 + CLIENT_PRINT(("> DDeviceIicClient::Install()"));
1.546 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::Install()"));
1.547 + return(SetName(&KLddRootName));
1.548 + }
1.549 +
1.550 +// Auxiliary functions for ordering entries in the array of TTransStatusPair pointers
1.551 +// The first is to enable searching by Transaction (used by the callback)
1.552 +// The second is to enable searching by the TRequestStatus (used by cancel calls)
1.553 +TInt OrderEntriesByTrans(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
1.554 + {
1.555 + TUint l=(TUint)(aMatch.iTrans);
1.556 + TUint r=(TUint)(aEntry.iTrans);
1.557 + if(l>r)
1.558 + return -1;
1.559 + else if(l<r)
1.560 + return 1;
1.561 + else
1.562 + return 0;
1.563 + }
1.564 +TLinearOrder<TTransStatusPair> TransStatusOrderByTrans(OrderEntriesByTrans);
1.565 +
1.566 +TInt OrderEntriesByStatus(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
1.567 + {
1.568 + TUint l=(TUint)(aMatch.iReq);
1.569 + TUint r=(TUint)(aEntry.iReq);
1.570 + if(l>r)
1.571 + return -1;
1.572 + else if(l<r)
1.573 + return 1;
1.574 + else
1.575 + return 0;
1.576 + }
1.577 +TLinearOrder<TTransStatusPair> TransStatusOrderByStatus(OrderEntriesByStatus);
1.578 +
1.579 +// Auxilliary function to track callback objects assigned to asynchronous transactions
1.580 +TInt OrderCbEntriesByTrans(const TTransCbPair& aMatch, const TTransCbPair& aEntry)
1.581 + {
1.582 + TUint l=(TUint)(aMatch.iTrans);
1.583 + TUint r=(TUint)(aEntry.iTrans);
1.584 + if(l>r)
1.585 + return -1;
1.586 + else if(l<r)
1.587 + return 1;
1.588 + else
1.589 + return 0;
1.590 + }
1.591 +TLinearOrder<TTransCbPair> TransCbOrderByTrans(OrderCbEntriesByTrans);
1.592 +
1.593 +TInt OrderExtractInfoByTrans(const TExtractInfo& aMatch, const TExtractInfo& aEntry)
1.594 + {
1.595 + TUint l=(TUint)(aMatch.iTrans);
1.596 + TUint r=(TUint)(aEntry.iTrans);
1.597 + if(l>r)
1.598 + return -1;
1.599 + else if(l<r)
1.600 + return 1;
1.601 + else
1.602 + return 0;
1.603 + }
1.604 +TLinearOrder<TExtractInfo> ExtractInfoOrderByTrans(OrderExtractInfoByTrans);
1.605 +
1.606 +
1.607 +_LIT(KLitArrayMutexName,"IIC_CLIENT_ARRAY_MUTEX");
1.608 +_LIT(KLitArraySemName,"IIC_CLIENT_ARRAY_SEM");
1.609 +#define IIC_CLIENT_MUTEX_ORDER KMutexOrdGeneral4 // Semi-arbitrary - middle of general purpose range, allow higher and lower priorities
1.610 +
1.611 +TInt DChannelIicClient::InitIicClient()
1.612 + {
1.613 + TInt r = Kern::MutexCreate(iArrayMutex,KLitArrayMutexName,IIC_CLIENT_MUTEX_ORDER);
1.614 + if(r!=KErrNone)
1.615 + return r;
1.616 + r = Kern::SemaphoreCreate(iChanArrWrtSem,KLitArraySemName,1); // Initial count of one allows first wait to be non-blocking
1.617 + if(r!=KErrNone)
1.618 + iArrayMutex->Close(NULL);
1.619 +
1.620 + return r;
1.621 + }
1.622 +
1.623 +TInt DChannelIicClient::InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair)
1.624 + {
1.625 + CLIENT_PRINT(("DChannelIicClient::InsertPairs invoked with aPair=0x%x, aPair->iReq=0x%x, aPair-iTrans=0x%x\n",aPair,aPair->iReq,aPair->iTrans ));
1.626 + CLIENT_PRINT(("DChannelIicClient::InsertPairs ... and aCbPair=0x%x, aCbPair->iCb=0x%x, aCbPair-iTrans=0x%x\n",aCbPair,aCbPair->iCb,aCbPair->iTrans ));
1.627 + TInt r = KErrNone;
1.628 +
1.629 + GetWriteAccess();
1.630 + Lock();
1.631 +
1.632 + if((r = iTransStatArrayByTrans.InsertInOrder(aPair,TransStatusOrderByTrans)) == KErrNone)
1.633 + {
1.634 + if((r = iTransStatArrayByStatus.InsertInOrder(aPair,TransStatusOrderByStatus)) == KErrNone)
1.635 + {
1.636 + if((r = iTransCbArrayByTrans.InsertInOrder(aCbPair,TransCbOrderByTrans))!=KErrNone)
1.637 + {
1.638 + CLIENT_PRINT(("DChannelIicClient::InsertPairs, aCbPair=0x%x InsertInOrder(status) returned %d\n",aCbPair,r));
1.639 + }
1.640 + }
1.641 + else
1.642 + {
1.643 + CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(status) returned %d\n",aPair,r));
1.644 + }
1.645 + }
1.646 + else
1.647 + {
1.648 + CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(trans) returned %d\n",aPair,r));
1.649 + }
1.650 + FreeWriteAccess();
1.651 + Unlock();
1.652 + return r;
1.653 + }
1.654 +
1.655 +//dummy call back func is provided for asyn call in priority test
1.656 +static void DummyCallbackFunc(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt /*aResult*/, TAny* /*aParam*/)
1.657 + {
1.658 + //do nothing
1.659 + }
1.660 +
1.661 +static void AsyncCallbackFunc(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam)
1.662 + {
1.663 + (void)aBusId; // aBusId is not used if CLIENT_PRINT is disabled
1.664 + CLIENT_PRINT(("> AsyncCallbackFunc() - aTrans=0x%x, aBusId=0x%x, aResult=%d, aParam=0x%x\n",aTrans,aBusId,aResult,aParam));
1.665 + DChannelIicClient* channel = (DChannelIicClient*)aParam;
1.666 + CLIENT_PRINT(("AsyncCallbackFunc() - channel=0x%x\n",channel));
1.667 +
1.668 + // Use the channel to get the user-side client's TRequestStatus and complete it with aResult
1.669 + TTransStatusPair* searchPair = new TTransStatusPair();
1.670 + searchPair->iTrans = aTrans;
1.671 + channel->GetWriteAccess();
1.672 + channel->Lock();
1.673 + TInt pairIndex = (channel->iTransStatArrayByTrans).FindInOrder(searchPair,TransStatusOrderByTrans);
1.674 + delete searchPair;
1.675 + if(pairIndex<0)
1.676 + {
1.677 + CLIENT_PRINT(("AsyncCallbackFunc() - (trans) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
1.678 + return;
1.679 + }
1.680 + TTransStatusPair* pairPtr = (channel->iTransStatArrayByTrans)[pairIndex];
1.681 + TRequestStatus* status = pairPtr->iReq;
1.682 +
1.683 + // Now remove the TTransStatusPair objects in iTransStatArrayByTrans, iTransStatArrayByStatus
1.684 + (channel->iTransStatArrayByTrans).Remove(pairIndex);
1.685 + pairIndex = (channel->iTransStatArrayByStatus).FindInOrder(pairPtr,TransStatusOrderByStatus);
1.686 + if(pairIndex<0)
1.687 + {
1.688 + CLIENT_PRINT(("AsyncCallbackFunc() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndex,status));
1.689 + return;
1.690 + }
1.691 + (channel->iTransStatArrayByStatus).Remove(pairIndex);
1.692 +
1.693 + // Now remove the TTransCbPair object in iTransCbArrayByTrans
1.694 + TTransCbPair* SearchCbPair = new TTransCbPair();
1.695 + SearchCbPair->iTrans = aTrans;
1.696 + pairIndex = (channel->iTransCbArrayByTrans).FindInOrder(SearchCbPair,TransCbOrderByTrans);
1.697 + delete SearchCbPair;
1.698 + if(pairIndex<0)
1.699 + {
1.700 + CLIENT_PRINT(("AsyncCallbackFunc() - (cb) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
1.701 + return;
1.702 + }
1.703 + TTransCbPair* cbPair = (channel->iTransCbArrayByTrans)[pairIndex];
1.704 + (channel->iTransCbArrayByTrans).Remove(pairIndex);
1.705 + delete cbPair->iCb;
1.706 + delete cbPair;
1.707 + channel->FreeWriteAccess();
1.708 + channel->Unlock();
1.709 + Kern::RequestComplete(channel->iClient, status, aResult);
1.710 + // We should call CleanupExtractTrans() to delete all the objects created in ExtractTransData()
1.711 + channel->CleanupExtractTrans(pairPtr->iTrans);
1.712 + // The object referred to be pairPtr is finished with and can be deleted
1.713 + channel->CleanupTransaction(pairPtr->iTrans);
1.714 + delete pairPtr;
1.715 + }
1.716 +
1.717 +
1.718 +void DDeviceIicClient::GetCaps(TDes8& aDes) const
1.719 +// Return the IicClient capabilities.
1.720 + {
1.721 + CLIENT_PRINT(("> DDeviceIicClient::GetCaps(TDes8& aDes) const"));
1.722 + TPckgBuf<TCapsIicClient> b;
1.723 + b().version=TVersion(KIicClientMajorVersionNumber,
1.724 + KIicClientMinorVersionNumber,
1.725 + KIicClientBuildVersionNumber);
1.726 + Kern::InfoCopy(aDes,b);
1.727 + }
1.728 +
1.729 +
1.730 +TInt DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)
1.731 +// Create a channel on the device.
1.732 + {
1.733 + CLIENT_PRINT(("> DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)"));
1.734 + if(iOpenChannels>=KMaxNumChannels)
1.735 + return KErrOverflow;
1.736 + aChannel=new DChannelIicClient;
1.737 + return aChannel?KErrNone:KErrNoMemory;
1.738 + }
1.739 +
1.740 +#ifdef STANDALONE_CHANNEL
1.741 +
1.742 +TInt GetChanPtr(const TInt aBusId, TInt &aIndex, DIicClientChan*& aChan)
1.743 + {
1.744 + __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
1.745 + TInt32 chanId;
1.746 + chanId = GET_CHAN_NUM(aBusId);
1.747 + __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, chanId=0x%x\n",chanId));
1.748 + DIicClientChan chanEntry(NULL,(TInt8)chanId, DIicBusChannel::EMasterSlave);
1.749 + TInt r = KErrNotFound;
1.750 + aIndex = ChannelArray.FindInOrder(&chanEntry, EntryOrder);
1.751 + if(aIndex >= 0)
1.752 + {
1.753 + aChan = ChannelArray[aIndex];
1.754 + r = KErrNone;
1.755 + }
1.756 +
1.757 + __KTRACE_OPT(KIIC, Kern::Printf("GetChanPtr, chanPtr=0x%x, index=%d\n",aChan,aIndex));
1.758 + return r;
1.759 + }
1.760 +#endif
1.761 +
1.762 +DECLARE_STANDARD_LDD()
1.763 + {
1.764 + //If in STANDALONE_CHANNEL mode, the client creates a list of channels
1.765 +#ifdef STANDALONE_CHANNEL
1.766 + DIicClientChan* aClientChan;
1.767 + TInt r = KErrNone;
1.768 + DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
1.769 + TInt i;
1.770 + for(i=0; i<NUM_CHANNELS_SPI; i++)
1.771 + {
1.772 + CLIENT_PRINT(("\n"));
1.773 +#if defined(MASTER_MODE)
1.774 + if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::EMaster))
1.775 + {
1.776 + chan=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
1.777 + if(!chan)
1.778 + {
1.779 + CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
1.780 + return NULL;
1.781 + }
1.782 + CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
1.783 + if(((DSimulatedIicBusChannelMasterSpi*)chan)->Create()!=KErrNone)
1.784 + {
1.785 + delete chan;
1.786 + return NULL;
1.787 + }
1.788 + aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMaster);
1.789 + if(!aClientChan)
1.790 + {
1.791 + delete chan;
1.792 + return NULL;
1.793 + }
1.794 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.795 + if(r!=KErrNone)
1.796 + {
1.797 + delete chan;
1.798 + delete aClientChan;
1.799 + break;
1.800 + }
1.801 + }
1.802 +#endif
1.803 +#if defined(MASTER_MODE) && defined(SLAVE_MODE)
1.804 + if(CHANNEL_TYPE_SPI(i) == DIicBusChannel::EMasterSlave)
1.805 + {
1.806 + //For MasterSlave channel, the client creates a Master channel, a Slave
1.807 + //channel and a MasterSlave Channel, then store all of them in ChannelArray.
1.808 + chanM=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
1.809 + if(!chanM)
1.810 + return NULL;
1.811 +
1.812 + chanS=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
1.813 + if(!chanS)
1.814 + {
1.815 + delete chanM;
1.816 + return NULL;
1.817 + }
1.818 + chan=new DIicBusChannelMasterSlave(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i),(DSimulatedIicBusChannelMasterSpi*)chanM,(DSimulatedIicBusChannelSlaveSpi*)chanS); // Generic implementation
1.819 + if(!chan)
1.820 + {
1.821 + CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
1.822 + delete chanM;
1.823 + delete chanS;
1.824 + return NULL;
1.825 + }
1.826 + CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
1.827 + if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
1.828 + {
1.829 + delete chanM;
1.830 + delete chanS;
1.831 + delete chan;
1.832 + return NULL;
1.833 + }
1.834 + aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMasterSlave);
1.835 + if(!aClientChan)
1.836 + {
1.837 + delete chanM;
1.838 + delete chanS;
1.839 + delete chan;
1.840 + return NULL;
1.841 + }
1.842 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.843 + if(r!=KErrNone)
1.844 + {
1.845 + delete chanM;
1.846 + delete chanS;
1.847 + delete chan;
1.848 + delete aClientChan;
1.849 + break;
1.850 + }
1.851 + }
1.852 +#endif
1.853 +#if defined(SLAVE_MODE)
1.854 + if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::ESlave))
1.855 + {
1.856 + chan=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
1.857 + if(!chan)
1.858 + {
1.859 + CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
1.860 + return NULL;
1.861 + }
1.862 + CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
1.863 + if(((DSimulatedIicBusChannelSlaveSpi*)chan)->Create()!=KErrNone)
1.864 + {
1.865 + delete chan;
1.866 + return NULL;
1.867 + }
1.868 + aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::ESlave);
1.869 + if(!aClientChan)
1.870 + {
1.871 + delete chan;
1.872 + return NULL;
1.873 + }
1.874 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.875 + if(r!=KErrNone)
1.876 + {
1.877 + delete chan;
1.878 + delete aClientChan;
1.879 + break;
1.880 + }
1.881 + }
1.882 +#endif
1.883 +#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
1.884 +#error I2C mode not defined as Master, Slave nor Master-Slave
1.885 +#endif
1.886 + }
1.887 +
1.888 + for(i=0; i<NUM_CHANNELS_I2C; i++)
1.889 + {
1.890 + CLIENT_PRINT(("\n"));
1.891 + #if defined(MASTER_MODE)
1.892 + if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::EMaster))
1.893 + {
1.894 + chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
1.895 + if(!chan)
1.896 + {
1.897 + CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
1.898 + return NULL;
1.899 + }
1.900 + CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
1.901 + if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
1.902 + {
1.903 + delete chan;
1.904 + return NULL;
1.905 + }
1.906 + aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
1.907 + if(!aClientChan)
1.908 + {
1.909 + delete chan;
1.910 + return NULL;
1.911 + }
1.912 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.913 + if(r!=KErrNone)
1.914 + {
1.915 + delete chan;
1.916 + delete aClientChan;
1.917 + break;
1.918 + }
1.919 + }
1.920 + #endif
1.921 + #if defined(MASTER_MODE) && defined(SLAVE_MODE)
1.922 + if(CHANNEL_TYPE_I2C(i) == DIicBusChannel::EMasterSlave)
1.923 + {
1.924 + chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
1.925 + if(!chanM)
1.926 + return NULL;
1.927 +
1.928 + chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
1.929 + if(!chanS)
1.930 + {
1.931 + delete chanM;
1.932 + return NULL;
1.933 + }
1.934 + //The client doesn't create the Master and Slave channels, as they should be created
1.935 + //in MasterSlave channel's DoCreate().
1.936 + chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
1.937 + if(!chan)
1.938 + {
1.939 + CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
1.940 + delete chanM;
1.941 + delete chanS;
1.942 + return NULL;
1.943 + }
1.944 + CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
1.945 + if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
1.946 + {
1.947 + delete chanM;
1.948 + delete chanS;
1.949 + delete chan;
1.950 + return NULL;
1.951 + }
1.952 + aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
1.953 + if(!aClientChan)
1.954 + {
1.955 + delete chanM;
1.956 + delete chanS;
1.957 + delete chan;
1.958 + return NULL;
1.959 + }
1.960 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.961 + if(r!=KErrNone)
1.962 + {
1.963 + delete chanM;
1.964 + delete chanS;
1.965 + delete chan;
1.966 + delete aClientChan;
1.967 + break;
1.968 + }
1.969 + }
1.970 + #endif
1.971 + #if defined(SLAVE_MODE)
1.972 + if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::ESlave))
1.973 + {
1.974 + chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
1.975 + if(!chan)
1.976 + {
1.977 + CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
1.978 + return NULL;
1.979 + }
1.980 + CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
1.981 + if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
1.982 + {
1.983 + delete chan;
1.984 + return NULL;
1.985 + }
1.986 + aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
1.987 + if(!aClientChan)
1.988 + {
1.989 + delete chan;
1.990 + return NULL;
1.991 + }
1.992 + r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
1.993 + if(r!=KErrNone)
1.994 + {
1.995 + delete chan;
1.996 + delete aClientChan;
1.997 + break;
1.998 + }
1.999 + }
1.1000 + #endif
1.1001 + #if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
1.1002 + #error I2C mode not defined as Master, Slave nor Master-Slave
1.1003 + #endif
1.1004 + }
1.1005 +
1.1006 +#endif
1.1007 + return new DDeviceIicClient;
1.1008 + }
1.1009 +
1.1010 +
1.1011 +
1.1012 +DChannelIicClient::DChannelIicClient()
1.1013 +// Constructor
1.1014 + {
1.1015 + CLIENT_PRINT(("> DChannelIicClient::DChannelIicClient()"));
1.1016 + iClient=&Kern::CurrentThread();
1.1017 + // Increase the DThread's ref count so that it does not close without us
1.1018 + iClient->Open();
1.1019 + }
1.1020 +
1.1021 +DChannelIicClient::~DChannelIicClient()
1.1022 +// Destructor
1.1023 + {
1.1024 + CLIENT_PRINT(("> DChannelIicClient::~DChannelIicClient()"));
1.1025 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelIicClient::~DChannelIicClient()"));
1.1026 + delete iNotif;
1.1027 + iArrayMutex->Close(NULL);
1.1028 + iChanArrWrtSem->Close(NULL);
1.1029 + iDfcQue->Destroy();
1.1030 + // decrement the DThread's reference count
1.1031 + Kern::SafeClose((DObject*&)iClient, NULL);
1.1032 +
1.1033 + iTransStatArrayByTrans.Reset();
1.1034 + iTransStatArrayByStatus.Reset();
1.1035 + iTransCbArrayByTrans.Reset();
1.1036 + iExtractInfoArray.Reset();
1.1037 + }
1.1038 +
1.1039 +
1.1040 +TInt DChannelIicClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.1041 + {
1.1042 + CLIENT_PRINT(("> DChannelIicClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
1.1043 + TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicClientThreadPriority,KIicClientThreadName);
1.1044 + if(r!=KErrNone)
1.1045 + return r;
1.1046 + SetDfcQ(iDfcQue);
1.1047 + iMsgQ.Receive();
1.1048 +
1.1049 + r = InitIicClient();
1.1050 + return r;
1.1051 + }
1.1052 +
1.1053 +void DChannelIicClient::HandleMsg(TMessageBase* aMsg)
1.1054 + {
1.1055 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.1056 + TInt id=m.iValue;
1.1057 +
1.1058 + CLIENT_PRINT((" >ldd: DChannelIicClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
1.1059 +
1.1060 + if (id == (TInt)ECloseMsg)
1.1061 + {
1.1062 + iMsgQ.iMessage->Complete(KErrNone,EFalse);
1.1063 + return;
1.1064 + }
1.1065 + else if (id == KMaxTInt)
1.1066 + {
1.1067 + DoCancel(m.Int0());
1.1068 + m.Complete(KErrNone,ETrue);
1.1069 + return;
1.1070 + }
1.1071 +
1.1072 + if (id<0)
1.1073 + {
1.1074 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.1075 + TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
1.1076 + if (r!=KErrNone)
1.1077 + {
1.1078 + Kern::RequestComplete(iClient, pS, r);
1.1079 + }
1.1080 + m.Complete(KErrNone,ETrue);
1.1081 + }
1.1082 + else
1.1083 + {
1.1084 + TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
1.1085 + m.Complete(r,ETrue);
1.1086 + }
1.1087 + }
1.1088 +
1.1089 +TInt DChannelIicClient::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback/*NULL*/)
1.1090 + {
1.1091 + TInt r = KErrNone;
1.1092 +#ifndef STANDALONE_CHANNEL
1.1093 + if(!aCallback)
1.1094 + r = IicBus::QueueTransaction(aBusId, aTransaction);
1.1095 + else
1.1096 + r = IicBus::QueueTransaction(aBusId, aTransaction, aCallback);
1.1097 +#else
1.1098 + __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1.1099 + if(!aTransaction)
1.1100 + {
1.1101 + return KErrArgument;
1.1102 + }
1.1103 +
1.1104 + // Get a pointer to the channel
1.1105 + TInt dumInt = 0;
1.1106 + DIicClientChan* chanPtr = NULL;
1.1107 + r = GetChanPtr(aBusId, dumInt, chanPtr);
1.1108 + if(r == KErrNone)
1.1109 + {
1.1110 + if(!chanPtr)
1.1111 + {
1.1112 + r = KErrArgument;
1.1113 + }
1.1114 + else
1.1115 + {
1.1116 + switch(chanPtr->GetChanType())
1.1117 + {
1.1118 + // QueueTransaction requests are only supported by channels in Master mode.
1.1119 + case DIicBusChannel::ESlave:
1.1120 + {
1.1121 + r = KErrNotSupported;
1.1122 + break;
1.1123 + }
1.1124 + // If the request is supported by the Master channel, send it to the channel for processing in its thread
1.1125 + case DIicBusChannel::EMasterSlave:
1.1126 + {
1.1127 +
1.1128 + aTransaction->iBusId = aBusId;
1.1129 + if(!aCallback)
1.1130 + r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
1.1131 + else
1.1132 + r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
1.1133 + break;
1.1134 + }
1.1135 + case DIicBusChannel::EMaster:
1.1136 + {
1.1137 + aTransaction->iBusId = aBusId;
1.1138 + if(!aCallback)
1.1139 + r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
1.1140 + else
1.1141 + r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
1.1142 + break;
1.1143 + }
1.1144 + default:
1.1145 + {
1.1146 + r = KErrGeneral;
1.1147 + }
1.1148 + }
1.1149 + }
1.1150 + }
1.1151 +#endif
1.1152 + return r;
1.1153 + }
1.1154 +
1.1155 +TInt DChannelIicClient::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1.1156 + {
1.1157 + TInt r = KErrNone;
1.1158 +#ifndef STANDALONE_CHANNEL
1.1159 + r = IicBus::CancelTransaction(aBusId, aTransaction);
1.1160 +#else
1.1161 + __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1.1162 + if(!aTransaction)
1.1163 + {
1.1164 + return KErrArgument;
1.1165 + }
1.1166 +
1.1167 + // Get the channel
1.1168 + TInt dumInt = 0;
1.1169 + DIicClientChan* chanPtr = NULL;
1.1170 + if(r == KErrNone)
1.1171 + {
1.1172 + r = GetChanPtr(aBusId, dumInt, chanPtr);
1.1173 + if(r == KErrNone)
1.1174 + {
1.1175 + if(!chanPtr)
1.1176 + {
1.1177 + r = KErrArgument;
1.1178 + }
1.1179 + else
1.1180 + {
1.1181 + // QueueTransaction requests are only supported by channels in Master mode.
1.1182 + switch(chanPtr->GetChanType())
1.1183 + {
1.1184 + case DIicBusChannel::ESlave:
1.1185 + {
1.1186 + r = KErrNotSupported;
1.1187 + break;
1.1188 + }
1.1189 + case DIicBusChannel::EMasterSlave:
1.1190 + {
1.1191 + r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
1.1192 + break;
1.1193 + }
1.1194 + case DIicBusChannel::EMaster:
1.1195 + {
1.1196 + r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
1.1197 + break;
1.1198 + }
1.1199 + default:
1.1200 + {
1.1201 + r = KErrGeneral;
1.1202 + }
1.1203 + }
1.1204 + }
1.1205 + }
1.1206 + }
1.1207 +#endif
1.1208 + return r;
1.1209 + }
1.1210 +
1.1211 +
1.1212 +TInt DChannelIicClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
1.1213 + {
1.1214 + TInt r = KErrNone;
1.1215 +#ifndef STANDALONE_CHANNEL
1.1216 + r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
1.1217 +#else
1.1218 + // Get the channel
1.1219 + TInt dumInt = 0;
1.1220 + DIicClientChan* chanPtr = NULL;
1.1221 + if(r == KErrNone)
1.1222 + {
1.1223 + r = GetChanPtr(aId, dumInt, chanPtr);
1.1224 + if(r == KErrNone)
1.1225 + {
1.1226 + if(!chanPtr)
1.1227 + {
1.1228 + r = KErrArgument;
1.1229 + }
1.1230 + else
1.1231 + {
1.1232 + r = (chanPtr->GetChannelPtr())->StaticExtension(aFunction, aParam1, aParam2);
1.1233 + }
1.1234 + }
1.1235 + }
1.1236 +#endif
1.1237 + return r;
1.1238 + }
1.1239 +
1.1240 +TInt DChannelIicClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
1.1241 + {
1.1242 + TInt r = KErrNone;
1.1243 +#ifndef STANDALONE_CHANNEL
1.1244 + r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
1.1245 +#else
1.1246 + // Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
1.1247 + if(!aCallback || !aConfigHdr)
1.1248 + {
1.1249 + return KErrArgument;
1.1250 + }
1.1251 +
1.1252 + // Get the channel
1.1253 + TInt chanIndex = 0;
1.1254 + DIicClientChan* chanPtr = NULL;
1.1255 + if(r == KErrNone)
1.1256 + {
1.1257 + r = GetChanPtr(aBusId, chanIndex, chanPtr);
1.1258 + if(r == KErrNone)
1.1259 + {
1.1260 + if(!chanPtr)
1.1261 + {
1.1262 + r = KErrArgument;
1.1263 + }
1.1264 + else
1.1265 + {
1.1266 + switch(chanPtr->GetChanType())
1.1267 + {
1.1268 + // CaptureChannel requests are only supported by channels in Slave mode.
1.1269 + case DIicBusChannel::EMaster:
1.1270 + {
1.1271 + r = KErrNotSupported;
1.1272 + break;
1.1273 + }
1.1274 + case DIicBusChannel::EMasterSlave:
1.1275 + {
1.1276 + r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
1.1277 + break;
1.1278 + }
1.1279 + case DIicBusChannel::ESlave:
1.1280 + {
1.1281 + r = ((DIicBusChannelSlave*)(chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
1.1282 + break;
1.1283 + }
1.1284 + default:
1.1285 + {
1.1286 + r = KErrArgument;
1.1287 + }
1.1288 + }
1.1289 + // For synchronous capture, if successful then install the channel
1.1290 + if(r == KErrNone)
1.1291 + {
1.1292 + if(!aAsynch)
1.1293 + {
1.1294 + iCapturedChannel.iChanPtr = chanPtr;
1.1295 + iCapturedChannel.iChannelId = iChannelId;
1.1296 + }
1.1297 + else
1.1298 + //For asynchronous capture, record chanPtr, if later failed capture,
1.1299 + //clean iCapturedChannel in client's callback.
1.1300 + iCapturedChannel.iChanPtr = chanPtr;
1.1301 + }
1.1302 + }
1.1303 + }
1.1304 + }
1.1305 +#endif
1.1306 + return r;
1.1307 + }
1.1308 +
1.1309 +TInt DChannelIicClient::ReleaseChannel(TInt aChannelId)
1.1310 + {
1.1311 + TInt r = KErrNone;
1.1312 +#ifndef STANDALONE_CHANNEL
1.1313 + r = IicBus::ReleaseChannel(aChannelId);
1.1314 +#else
1.1315 + __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
1.1316 + if(iCapturedChannel.iChannelId != aChannelId)
1.1317 + return KErrNotFound;
1.1318 +
1.1319 + if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::EMasterSlave)
1.1320 + r = ((DIicBusChannelMasterSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
1.1321 + else if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::ESlave)
1.1322 + r = ((DIicBusChannelSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
1.1323 + //After release channel, reset iCapturedChan
1.1324 + iCapturedChannel.iChanPtr = NULL;
1.1325 + iCapturedChannel.iChannelId = 0;
1.1326 +#endif
1.1327 + return r;
1.1328 + }
1.1329 +
1.1330 +void DChannelIicClient::DoCancel(TInt aMask)
1.1331 + {
1.1332 +// Cancel an outstanding request.
1.1333 + CLIENT_PRINT(("DChannelIicClient::DoCancel invoked with aMask=0x%x\n", aMask));
1.1334 +
1.1335 + // inline void CancelAsyncOperation(TRequestStatus* aStatus, TInt aBusId) {TInt* parms[2]; parms[0]=(TInt*)aStatus; parms[1]=(TInt*)aBusId;DoCancel((TInt)&parms[0]);}
1.1336 + // aMask has the address on TInt* parms[2]
1.1337 + // parms[0] = TRequestStatus pointer
1.1338 + // parms[1] = Bus Identifier
1.1339 + TInt* parms[2];
1.1340 + TInt r=Kern::ThreadRawRead(iClient,(TAny*)aMask,&(parms[0]),2*sizeof(TInt*));
1.1341 + if(r!=KErrNone)
1.1342 + {
1.1343 + CLIENT_PRINT(("DChannelIicClient::DoCancel ERROR - Can't read parms[]\n"));
1.1344 + return; // Can't proceed if can't access request parameters
1.1345 + }
1.1346 + CLIENT_PRINT(("DChannelIicClient::DoCancel - TRequestStatus 0x%x, BusID = 0x%x\n",parms[0],parms[1]));
1.1347 +
1.1348 + TTransStatusPair* searchPair = new TTransStatusPair();
1.1349 + TTransCbPair* cbPair = new TTransCbPair();
1.1350 + searchPair->iReq = (TRequestStatus*)(parms[0]);
1.1351 +
1.1352 + GetWriteAccess();
1.1353 + Lock();
1.1354 +
1.1355 + TInt pairIndexByStatus = iTransStatArrayByStatus.FindInOrder(searchPair,TransStatusOrderByStatus);
1.1356 + CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByStatus=0x%x\n",pairIndexByStatus));
1.1357 + TInt pairIndexByTrans = KErrNotFound;
1.1358 +
1.1359 + if(pairIndexByStatus<0)
1.1360 + {
1.1361 + // If the TRequestStatus object is not found then either the value was invalid or
1.1362 + // the object may already have been completed.
1.1363 + FreeWriteAccess();
1.1364 + Unlock();
1.1365 + CLIENT_PRINT(("DChannelIicClient::DoCancel() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndexByStatus,parms[0]));
1.1366 + }
1.1367 + else
1.1368 + {
1.1369 + // The status-transaction pair exists in the status-index array - so remove it
1.1370 + TTransStatusPair* pairPtrStatus = iTransStatArrayByStatus[pairIndexByStatus];
1.1371 + iTransStatArrayByStatus.Remove(pairIndexByStatus);
1.1372 +
1.1373 + pairIndexByTrans = iTransStatArrayByTrans.FindInOrder(pairPtrStatus,TransStatusOrderByTrans);
1.1374 + CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByTrans=0x%x\n",pairIndexByTrans));
1.1375 + if(pairIndexByTrans>=0)
1.1376 + {
1.1377 + iTransStatArrayByTrans.Remove(pairIndexByTrans);
1.1378 + }
1.1379 + FreeWriteAccess();
1.1380 + Unlock();
1.1381 +
1.1382 + CLIENT_PRINT(("DChannelIicClient::DoCancel pairPtrStatus=0x%x\n", pairPtrStatus));
1.1383 +
1.1384 + // Allow the bus to perform any required processing
1.1385 + TIicBusTransaction* trans = pairPtrStatus->iTrans;
1.1386 + CLIENT_PRINT(("DChannelIicClient::CancelTransaction - invoking with busId=0x%x, trans=0x%x\n",(TInt)(parms[1]),trans));
1.1387 + r = CancelTransaction((TInt)(parms[1]), trans);
1.1388 + cbPair->iTrans=trans;
1.1389 + TInt cbIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
1.1390 + TTransCbPair* theCbPair = iTransCbArrayByTrans[cbIndex];
1.1391 + TIicBusCallback* cb= (iTransCbArrayByTrans[cbIndex])->iCb;
1.1392 + iTransCbArrayByTrans.Remove(cbIndex);
1.1393 +
1.1394 + // Complete the TRequestStatus object according to the returned value
1.1395 + TRequestStatus* status= (TRequestStatus*)(parms[0]);
1.1396 + Kern::RequestComplete(iClient, status, r);
1.1397 +
1.1398 + // Clean up
1.1399 + delete cb;
1.1400 + delete theCbPair;
1.1401 + // We should call CleanupExtractTrans() to delete all the objects we created in ExtractTransData()
1.1402 + CleanupExtractTrans(trans);
1.1403 + CleanupTransaction(trans);
1.1404 + delete pairPtrStatus;
1.1405 + }
1.1406 +
1.1407 + delete cbPair;
1.1408 + delete searchPair;
1.1409 +
1.1410 + return;
1.1411 + }
1.1412 +
1.1413 +
1.1414 +// Function to support preamble testing
1.1415 +void PreambleCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
1.1416 + {
1.1417 + CLIENT_PRINT(("IIC Client: PreambleCallbackFunc invoked\n"));
1.1418 + // aParam is the address of the client that created the transaction object
1.1419 + __ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("PreambleCallbackFunc, client address ==NULL",__LINE__));
1.1420 + DChannelIicClient *client = (DChannelIicClient*)aParam;
1.1421 + __ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("PreambleCallbackFunc, iClient==NULL",__LINE__));
1.1422 + __ASSERT_ALWAYS(client->iPreambleStatus!=NULL,Kern::Fault("PreambleCallbackFunc, iPreambleStatus==NULL",__LINE__));
1.1423 + Kern::RequestComplete(client->iClient, client->iPreambleStatus, KErrNone);
1.1424 + }
1.1425 +
1.1426 +TIicBusTransaction* DChannelIicClient::iMultiTransac;
1.1427 +
1.1428 +// Function to support multi transc testing
1.1429 +TIicBusTransaction* DChannelIicClient::MultiTranscCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
1.1430 + {
1.1431 + CLIENT_PRINT(("IIC Client: MultiTranscCallbackFunc invoked\n"));
1.1432 + // aParam is the address of the client that created the transaction object
1.1433 + __ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("MultiTranscCallbackFunc, client address ==NULL",__LINE__));
1.1434 + DChannelIicClient *client = (DChannelIicClient*)aParam;
1.1435 + __ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("MultiTranscCallbackFunc, iClient==NULL",__LINE__));
1.1436 + __ASSERT_ALWAYS(client->iMultiTranscStatus!=NULL,Kern::Fault("MultiTranscCallbackFunc, iMultiTranscStatus==NULL",__LINE__));
1.1437 + Kern::RequestComplete(client->iClient, client->iMultiTranscStatus, KErrNone);
1.1438 + return iMultiTransac;
1.1439 + }
1.1440 +
1.1441 +TInt DChannelIicClient::CleanupExtractTrans(TIicBusTransaction* aTrans)
1.1442 + {
1.1443 + // Clean up the data created in ExtractTransData()
1.1444 + TExtractInfo *extractInfo = new TExtractInfo();
1.1445 + extractInfo->iTrans = aTrans;
1.1446 + TInt index = iExtractInfoArray.FindInOrder(extractInfo, ExtractInfoOrderByTrans);
1.1447 + if(index >= 0)
1.1448 + {
1.1449 + delete iExtractInfoArray[index];
1.1450 + iExtractInfoArray.Remove(index);
1.1451 + }
1.1452 + delete extractInfo;
1.1453 + return KErrNone;
1.1454 + }
1.1455 +
1.1456 +TInt DChannelIicClient::ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans)
1.1457 + {
1.1458 +// Utility function to create a TIicBusTransaction object from the parameters passed by the user-side TUsideTracnDesc object
1.1459 +
1.1460 + TInt r = KErrNone;
1.1461 + TUsideTracnDesc usTrans;
1.1462 + r=Kern::ThreadRawRead(iClient,aUsideTrancnDesc,&usTrans,sizeof(TUsideTracnDesc));
1.1463 + if(r!=KErrNone)
1.1464 + {
1.1465 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans\n"));
1.1466 + return KErrGeneral; // Can't proceed if can't access request parameters
1.1467 + }
1.1468 + // Ensure pointers potentially used for allocation are NULL, to facilitate cleanup
1.1469 + iSpiBuf=NULL;
1.1470 + iI2cBuf=NULL;
1.1471 + iTfer=NULL;
1.1472 + iTransPreamble=NULL;
1.1473 + iFdTfer=NULL;
1.1474 +
1.1475 + // Get the header (depends on the bus type)
1.1476 + TBusType busType = usTrans.iType;
1.1477 + TConfigSpiBufV01 *spiBuf = NULL;
1.1478 + TConfigI2cBufV01 *i2cBuf = NULL;
1.1479 + // extractInfo is used to keep the bufPtr and tfer of the transaction,
1.1480 + // and will later be stored in iExtractInfoArray, sorting by transaction.
1.1481 + // The extractInfo object will be freed in CleanupExtractTrans.
1.1482 + TExtractInfo *extractInfo = new TExtractInfo();
1.1483 + TDes8* bufPtr=NULL;
1.1484 + if(busType == ESpi)
1.1485 + {
1.1486 + if((spiBuf = new TConfigSpiBufV01()) == NULL)
1.1487 + {
1.1488 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate spiBuf\n"));
1.1489 + return KErrNoMemory;
1.1490 + }
1.1491 + if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
1.1492 + {
1.1493 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to spiBuf\n"));
1.1494 + return KErrGeneral;
1.1495 + }
1.1496 + bufPtr=(TDes8*)spiBuf;
1.1497 + }
1.1498 + else if(busType == EI2c)
1.1499 + {
1.1500 + if((i2cBuf = new TConfigI2cBufV01()) == NULL)
1.1501 + {
1.1502 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate i2cBuf\n"));
1.1503 + return KErrNoMemory;
1.1504 + }
1.1505 + if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *i2cBuf, 0, KChunkShiftBy0 ))!=KErrNone)
1.1506 + {
1.1507 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to i2cBuf\n"));
1.1508 + return KErrGeneral;
1.1509 + }
1.1510 + bufPtr=(TDes8*)i2cBuf;
1.1511 + }
1.1512 + else
1.1513 + {
1.1514 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unrecognised bus type\n"));
1.1515 + return KErrGeneral;
1.1516 + }
1.1517 + extractInfo->iBufPtr = bufPtr;
1.1518 + // Get the half-duplex transfer information
1.1519 + TUsideTferDesc* usTferPtr = usTrans.iHalfDuplexTrans;
1.1520 + TUsideTferDesc usTfer;
1.1521 + r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
1.1522 + if(r!=KErrNone)
1.1523 + {
1.1524 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex usTfer\n"));
1.1525 + return KErrGeneral; // Can't proceed if can't access request parameters
1.1526 + }
1.1527 + // Need to access the descriptor holding the information to be transferred
1.1528 + TBuf8 <MAX_TRANS_LENGTH> tferData;
1.1529 + r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,tferData,0,KChunkShiftBy0);
1.1530 + if(r!=KErrNone)
1.1531 + {
1.1532 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex tferData\n"));
1.1533 + return KErrGeneral; // Can't proceed if can't access request parameters
1.1534 + }
1.1535 +
1.1536 + TIicBusTransfer::TReqType type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
1.1537 + tfer7 = new TIicBusTransfer(type, usTfer.iBufGranularity, &tferData);
1.1538 + extractInfo->iTfer = tfer7;
1.1539 + // Construct the appropriate transaction object with the half-duplex information
1.1540 + TUint8 transFlags = usTrans.iFlags;
1.1541 +
1.1542 + if((transFlags&KTransactionWithPreamble)&&(transFlags&KTransactionWithMultiTransc))
1.1543 + {
1.1544 + if(usTrans.iPreambleArg == NULL)
1.1545 + {
1.1546 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
1.1547 + return KErrArgument;
1.1548 + }
1.1549 + if(usTrans.iMultiTranscArg == NULL)
1.1550 + {
1.1551 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
1.1552 + return KErrArgument;
1.1553 + }
1.1554 + iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
1.1555 + iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
1.1556 + TIicBusTransactionPreambleExt* transExt;
1.1557 +
1.1558 + transExt = new TIicBusTransactionPreambleExt(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this,
1.1559 + (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
1.1560 + if(transExt == NULL)
1.1561 + {
1.1562 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1.1563 + return KErrNoMemory; // Can't proceed if can't access request parameters
1.1564 + }
1.1565 + aTrans = transExt;
1.1566 +
1.1567 + }
1.1568 + else if(transFlags & KTransactionWithPreamble)
1.1569 + {
1.1570 + // Preamble required - construct the derived-class transaction object
1.1571 + if(usTrans.iPreambleArg == NULL)
1.1572 + {
1.1573 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - preamble TRequestStatus==NULL\n"));
1.1574 + return KErrArgument;
1.1575 + }
1.1576 + iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
1.1577 + TIicBusTransactionPreamble* TransPreamble;
1.1578 + TransPreamble = new TIicBusTransactionPreamble(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this);
1.1579 + if(TransPreamble == NULL)
1.1580 + {
1.1581 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1.1582 + return KErrNoMemory; // Can't proceed if can't access request parameters
1.1583 + }
1.1584 + aTrans = TransPreamble;
1.1585 + }
1.1586 + else if(transFlags & KTransactionWithMultiTransc)
1.1587 + {
1.1588 + // Preamble required - construct the derived-class transaction object
1.1589 + if(usTrans.iMultiTranscArg == NULL)
1.1590 + {
1.1591 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Multi Transc TRequestStatus==NULL\n"));
1.1592 + return KErrArgument;
1.1593 + }
1.1594 + iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
1.1595 + TIicBusTransactionMultiTransc* transMultiTransc;
1.1596 + transMultiTransc = new TIicBusTransactionMultiTransc(bufPtr, tfer7, (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
1.1597 + if(transMultiTransc == NULL)
1.1598 + {
1.1599 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1.1600 + return KErrNoMemory; // Can't proceed if can't access request parameters
1.1601 + }
1.1602 + aTrans = transMultiTransc;
1.1603 + }
1.1604 + else
1.1605 + {
1.1606 + // Preamble not required
1.1607 + aTrans = new TIicBusTransaction(bufPtr, tfer7);
1.1608 + if(aTrans == NULL)
1.1609 + {
1.1610 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
1.1611 + return KErrNoMemory; // Can't proceed if can't access request parameters
1.1612 + }
1.1613 + }
1.1614 +
1.1615 + // If full duplex transaction is required get that information, too
1.1616 + usTferPtr = usTrans.iFullDuplexTrans;
1.1617 + if(usTferPtr!=NULL)
1.1618 + {
1.1619 + r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
1.1620 + if(r!=KErrNone)
1.1621 + {
1.1622 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex usTfer\n"));
1.1623 + return KErrGeneral; // Can't proceed if can't access request parameters
1.1624 + }
1.1625 + // Need to access the descriptor holding the information to be transferred
1.1626 + TBuf8 <MAX_TRANS_LENGTH> fdTferData;
1.1627 + r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,fdTferData,0,KChunkShiftBy0);
1.1628 + if(r!=KErrNone)
1.1629 + {
1.1630 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex tferData\n"));
1.1631 + return KErrGeneral; // Can't proceed if can't access request parameters
1.1632 + }
1.1633 +
1.1634 + type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
1.1635 + r=aTrans->SetFullDuplexTrans(iFdTfer);
1.1636 + if(r!=KErrNone)
1.1637 + {
1.1638 + CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - SetFullDuplexTrans returned %d\n",r));
1.1639 + return r;
1.1640 + }
1.1641 + }
1.1642 + extractInfo->iTrans = aTrans;
1.1643 + iExtractInfoArray.InsertInOrder(extractInfo, ExtractInfoOrderByTrans);
1.1644 + return r;
1.1645 + }
1.1646 +
1.1647 +#define KMaxTferTextLength 20
1.1648 +#define KLongNodeTestLength 15
1.1649 +#define KShortNodeTestLength 5
1.1650 +_LIT(KFullTracnHdrText,"Full duplex test"); // length = 22
1.1651 +#define KFullTracnHdrTextLength 16
1.1652 +
1.1653 +
1.1654 +// Create transfer list with three nodes
1.1655 +// All memories are allocated from the kernel heap and referenced by class members
1.1656 +// DeleteFullDuplexTest should be called to release memory after use.
1.1657 +// List created here will be assigned to iHalfDuplexTrans in TIicBusTransaction
1.1658 +// If aNodeLength3 = 0, only return a 2 nodes transfer
1.1659 +TInt DChannelIicClient::CreateTransferListHalfDuplex(
1.1660 + TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1.1661 + TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1.1662 + TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
1.1663 + {
1.1664 + buf1 = HBuf8::New(KMaxTferTextLength);
1.1665 + buf2 = HBuf8::New(KMaxTferTextLength);
1.1666 + buf3 = HBuf8::New(KMaxTferTextLength);
1.1667 + tfer1 = new TIicBusTransfer(aNodeDir1,8,buf1);
1.1668 + tfer2 = new TIicBusTransfer(aNodeDir2,8,buf2);
1.1669 + tfer3 = new TIicBusTransfer(aNodeDir3,8,buf3);
1.1670 +
1.1671 + if(buf1 == NULL||buf2 == NULL||buf3 == NULL||
1.1672 + tfer1 == NULL||tfer2 == NULL||tfer3 == NULL)
1.1673 + {
1.1674 + delete buf1; delete buf2; delete buf3;
1.1675 + delete tfer1; delete tfer2; delete tfer3;
1.1676 + return KErrNoMemory;
1.1677 + }
1.1678 +
1.1679 + TInt i;
1.1680 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf1->Append('*');
1.1681 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf2->Append('*');
1.1682 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf3->Append('*');
1.1683 +
1.1684 + tfer1->LinkAfter(tfer2);
1.1685 +
1.1686 + //allow two nodes
1.1687 + if(aNodeLength3>0)
1.1688 + {
1.1689 + tfer2->LinkAfter(tfer3);
1.1690 + }
1.1691 +
1.1692 + return KErrNone;
1.1693 +
1.1694 + }
1.1695 +
1.1696 +// Create transfer list with three nodes
1.1697 +// All memories are allocated from the kernel heap and referenced by class members
1.1698 +// DeleteFullDuplexTest should be called to release memory after use.
1.1699 +// List created here will be assigned to iFullDuplexTrans in TIicBusTransaction
1.1700 +// If aNodeLength3 = 0, only return a 2 nodes transfer
1.1701 +TInt DChannelIicClient::CreateTransferListFullDuplex(
1.1702 + TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
1.1703 + TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
1.1704 + TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
1.1705 + {
1.1706 + buf4 = HBuf8::New(KMaxTferTextLength);
1.1707 + buf5 = HBuf8::New(KMaxTferTextLength);
1.1708 + buf6 = HBuf8::New(KMaxTferTextLength);
1.1709 + tfer4 = new TIicBusTransfer(aNodeDir1,8,buf4);
1.1710 + tfer5 = new TIicBusTransfer(aNodeDir2,8,buf5);
1.1711 + tfer6 = new TIicBusTransfer(aNodeDir3,8,buf6);
1.1712 +
1.1713 + if(buf4 == NULL||buf5 == NULL||buf6 == NULL||
1.1714 + tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
1.1715 + {
1.1716 + delete buf4; delete buf5; delete buf6;
1.1717 + delete tfer4; delete tfer5; delete tfer6;
1.1718 + return KErrNoMemory;
1.1719 + }
1.1720 +
1.1721 + TInt i;
1.1722 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf4->Append('*');
1.1723 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf5->Append('*');
1.1724 + for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf6->Append('*');
1.1725 +
1.1726 + tfer4->LinkAfter(tfer5);
1.1727 +
1.1728 + //allow two nodes
1.1729 + if(aNodeLength3>0)
1.1730 + {
1.1731 + tfer5->LinkAfter(tfer6);
1.1732 + }
1.1733 +
1.1734 + return KErrNone;
1.1735 +
1.1736 + }
1.1737 +
1.1738 +// Delete transaction and all allocated transfers and buffers
1.1739 +TInt DChannelIicClient::DeleteFullDuplexTest(TIicBusTransaction *aTrans)
1.1740 + {
1.1741 + delete buf1; delete buf2; delete buf3;
1.1742 + delete tfer1; delete tfer2; delete tfer3;
1.1743 +
1.1744 + delete buf4; delete buf5; delete buf6;
1.1745 + delete tfer4; delete tfer5; delete tfer6;
1.1746 +
1.1747 + delete header;
1.1748 + delete aTrans;
1.1749 +
1.1750 + return KErrNone;
1.1751 + }
1.1752 +
1.1753 +// Do full duplex creation test
1.1754 +TInt DChannelIicClient::DoCreateFullDuplexTransTest(TInt aTestType)
1.1755 + {
1.1756 + CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest starts\n"));
1.1757 +
1.1758 + TInt r=KErrNone;
1.1759 + switch(aTestType)
1.1760 + {
1.1761 + case RBusDevIicClient::ETestValidFullDuplexTrans:
1.1762 + {
1.1763 + // equal length, opposite transfer direction
1.1764 + r = CreateTransferListHalfDuplex(
1.1765 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1766 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1767 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1.1768 + if(r!=KErrNone) break;
1.1769 + r = CreateTransferListFullDuplex(
1.1770 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1771 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1772 + TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1.1773 + if(r!=KErrNone) break;
1.1774 + break;
1.1775 + }
1.1776 + case RBusDevIicClient::ETestInvalidFullDuplexTrans1:
1.1777 + {
1.1778 + // equal length, same transfer direction
1.1779 + r = CreateTransferListHalfDuplex(
1.1780 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1781 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1782 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1.1783 + if(r!=KErrNone) break;
1.1784 + r = CreateTransferListFullDuplex(
1.1785 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1786 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1787 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
1.1788 + if(r!=KErrNone) break;
1.1789 + break;
1.1790 + }
1.1791 + case RBusDevIicClient::ETestInvalidFullDuplexTrans2:
1.1792 + {
1.1793 + // different, opposite transfer direction
1.1794 + r = CreateTransferListHalfDuplex(
1.1795 + TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
1.1796 + TIicBusTransfer::EMasterRead, KShortNodeTestLength,
1.1797 + TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1.1798 + if(r!=KErrNone) break;
1.1799 + r = CreateTransferListFullDuplex(
1.1800 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1801 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1802 + TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1.1803 + if(r!=KErrNone) break;
1.1804 + break;
1.1805 + }
1.1806 + case RBusDevIicClient::ETestLastNodeFullDuplexTrans:
1.1807 + {
1.1808 + // different length for the last node
1.1809 + r = CreateTransferListHalfDuplex(
1.1810 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1811 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1812 + TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1.1813 + if(r!=KErrNone) break;
1.1814 + r = CreateTransferListFullDuplex(
1.1815 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1816 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1817 + TIicBusTransfer::EMasterRead, KLongNodeTestLength);
1.1818 + if(r!=KErrNone) break;
1.1819 + break;
1.1820 + }
1.1821 + case RBusDevIicClient::ETestDiffNodeNoFullDuplexTrans:
1.1822 + {
1.1823 + // equal length, opposite transfer direction
1.1824 + r = CreateTransferListHalfDuplex(
1.1825 + TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
1.1826 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1827 + TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
1.1828 + if(r!=KErrNone) break;
1.1829 + r = CreateTransferListFullDuplex(
1.1830 + TIicBusTransfer::EMasterRead, KLongNodeTestLength,
1.1831 + TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
1.1832 + TIicBusTransfer::EMasterRead, 0);
1.1833 + if(r!=KErrNone) break;
1.1834 + break;
1.1835 + }
1.1836 +
1.1837 +
1.1838 + default:
1.1839 + break;
1.1840 + }
1.1841 +
1.1842 + header = HBuf8::New(KFullTracnHdrTextLength);
1.1843 + TIicBusTransaction *Trans = new TIicBusTransaction(header,tfer1);
1.1844 +
1.1845 + if((r!=KErrNone) || (header == NULL) || (Trans == NULL))
1.1846 + {
1.1847 + CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest ERROR - failed to allocate the necessary memory\n"));
1.1848 + DeleteFullDuplexTest(Trans);
1.1849 + return KErrNoMemory;
1.1850 + }
1.1851 +
1.1852 + header->Copy(KFullTracnHdrText);
1.1853 +
1.1854 + TInt TestResult = Trans->SetFullDuplexTrans(tfer4);
1.1855 +
1.1856 + CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest IIC after SetFullDuplexTrans TestResult =%d\n", TestResult));
1.1857 +
1.1858 + r = DeleteFullDuplexTest(Trans);
1.1859 +
1.1860 + return TestResult;
1.1861 +
1.1862 + }
1.1863 +
1.1864 +
1.1865 +TInt DChannelIicClient::CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf)
1.1866 +// Utility function to create a buffer for the SPI bus
1.1867 + {
1.1868 + TInt r=CreateSpiBuf(aBuf, ESpiWordWidth_8, 100000, ESpiPolarityLowRisingEdge, 100 ,ELittleEndian, EMsbFirst, 10, ESpiCSPinActiveLow);
1.1869 + return r;
1.1870 + }
1.1871 +
1.1872 +// DoPriorityTest does the following actions:
1.1873 +// 1. switch the bus (only use SPI test PSL) to priority test mode
1.1874 +// 2. create 5 test transactions with different priorities and 1 blocking transaction
1.1875 +// 3. enable blocking in test channel
1.1876 +// we can only block the test channel, we cannot suspend the bus controller
1.1877 +// 3. send blocking transaction to the test channel
1.1878 +// the blocking transaction is just normal transaction.
1.1879 +// the test channel will be blocked once the first transaction is arrived
1.1880 +// 4. send test transactions in opposite order to their priority
1.1881 +// 5. unblock test channel
1.1882 +// 6. read test result from channel
1.1883 +// 7. switch the bus to normal mode
1.1884 +TInt DChannelIicClient::DoPriorityTest(TInt aBusId)
1.1885 + {
1.1886 + TInt TestResult=KErrNone;
1.1887 + // Use the IIC StaticExtension interface to pass the request to the bus implementation
1.1888 + // To support testing, any values of aId for StaticExtension must be shifted left one place
1.1889 + TUint testId = ((TUint)(RBusDevIicClient::ECtlIoPriorityTest))<<1;
1.1890 + TInt r = KErrNone;
1.1891 +
1.1892 + r = StaticExtension(aBusId, testId, NULL, NULL);
1.1893 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1894 + if(r == KErrNone)
1.1895 + {
1.1896 + buf1 = HBuf8::New(1);
1.1897 + buf2 = HBuf8::New(1);
1.1898 + buf3 = HBuf8::New(1);
1.1899 + buf4 = HBuf8::New(1);
1.1900 + buf5 = HBuf8::New(1);
1.1901 + //buffer for blocking transaction
1.1902 + buf6 = HBuf8::New(1);
1.1903 +
1.1904 + if(buf1 == NULL||buf2 == NULL||buf3 == NULL||buf4 == NULL||buf5 == NULL||buf6 == NULL)
1.1905 + {
1.1906 + delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1.1907 + r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.1908 + return KErrNoMemory;
1.1909 + }
1.1910 + tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
1.1911 + tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf2);
1.1912 + tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
1.1913 + tfer4 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf4);
1.1914 + tfer5 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf5);
1.1915 + //transfer for blocking transaction
1.1916 + tfer6 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf6);
1.1917 +
1.1918 + if(tfer1 == NULL||tfer2 == NULL||tfer3 == NULL||tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
1.1919 + {
1.1920 + delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1.1921 + delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1.1922 + r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.1923 + return KErrNoMemory;
1.1924 + }
1.1925 +
1.1926 + TConfigSpiBufV01* spiHeader1 = NULL;
1.1927 + TConfigSpiBufV01* spiHeader2 = NULL;
1.1928 + TConfigSpiBufV01* spiHeader3 = NULL;
1.1929 + TConfigSpiBufV01* spiHeader4 = NULL;
1.1930 + TConfigSpiBufV01* spiHeader5 = NULL;
1.1931 + TConfigSpiBufV01* spiHeaderBlock = NULL; //header for blocking transaction
1.1932 +
1.1933 +
1.1934 + TInt r = CreateDefaultSpiBuf(spiHeader1);
1.1935 + if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader2);
1.1936 + if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader3);
1.1937 + if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader4);
1.1938 + if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeader5);
1.1939 + //header for blocking transaction
1.1940 + if(r == KErrNone) r = CreateDefaultSpiBuf(spiHeaderBlock);
1.1941 +
1.1942 + if(r != KErrNone||spiHeader1 == NULL||spiHeader2 == NULL||spiHeader3 == NULL||spiHeader4 == NULL||spiHeader5 == NULL||spiHeaderBlock == NULL)
1.1943 + {
1.1944 + delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1.1945 + delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1.1946 + delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
1.1947 + r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.1948 + return KErrNoMemory;
1.1949 + }
1.1950 +
1.1951 + TIicBusTransaction* Transc1; Transc1 = new TIicBusTransaction(spiHeader1,tfer1, KPriorityTestPrio[0]);
1.1952 + TIicBusTransaction* Transc2; Transc2 = new TIicBusTransaction(spiHeader2,tfer2, KPriorityTestPrio[1]);
1.1953 + TIicBusTransaction* Transc3; Transc3 = new TIicBusTransaction(spiHeader3,tfer3, KPriorityTestPrio[2]);
1.1954 + TIicBusTransaction* Transc4; Transc4 = new TIicBusTransaction(spiHeader4,tfer4, KPriorityTestPrio[3]);
1.1955 + TIicBusTransaction* Transc5; Transc5 = new TIicBusTransaction(spiHeader5,tfer5, KPriorityTestPrio[4]);
1.1956 + //blocking transaction
1.1957 + TIicBusTransaction* TranscBlock; TranscBlock = new TIicBusTransaction(spiHeaderBlock,tfer6, KPriorityTestPrio[5]);
1.1958 +
1.1959 + if(Transc1 == NULL||Transc2 == NULL||Transc3 == NULL||Transc4 == NULL||Transc5 == NULL||TranscBlock == NULL)
1.1960 + {
1.1961 + delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1.1962 + delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1.1963 + delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
1.1964 + delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
1.1965 + r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.1966 + return KErrNoMemory;
1.1967 + }
1.1968 +
1.1969 + //dummy call back func is provided for asyn call
1.1970 + TIicBusCallback* cb = new TIicBusCallback(DummyCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
1.1971 +
1.1972 + // block the device channel. the channel will not be blocked until the first transaction arrive the channel
1.1973 + // To support testing, any values of aId for StaticExtension must be shifted left one place
1.1974 + TUint testId=((TUint)RBusDevIicClient::ECtlIoBlockReqCompletion)<<1;
1.1975 + r = StaticExtension(aBusId, testId, NULL, NULL);
1.1976 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1977 +
1.1978 + r = QueueTransaction(aBusId, TranscBlock, cb); //send TranscBlock to block the channel
1.1979 + // send ordered transactions
1.1980 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1981 +
1.1982 + r = QueueTransaction(aBusId, Transc1, cb);
1.1983 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1984 + r = QueueTransaction(aBusId, Transc2, cb);
1.1985 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1986 + r = QueueTransaction(aBusId, Transc3, cb);
1.1987 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1988 + r = QueueTransaction(aBusId, Transc4, cb);
1.1989 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1990 + r = QueueTransaction(aBusId, Transc5, cb);
1.1991 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1992 +
1.1993 + // unblock device channel
1.1994 + testId=((TUint)RBusDevIicClient::ECtlIoUnblockReqCompletion)<<1;
1.1995 + r = StaticExtension(aBusId, testId, NULL, NULL);
1.1996 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.1997 +
1.1998 + #define KPriorityTestGetResultRetry 3
1.1999 + for(TInt i=0; i<KPriorityTestGetResultRetry ; i++)
1.2000 + {
1.2001 + NKern::Sleep(500);
1.2002 + testId=((TUint)RBusDevIicClient::EGetTestResult)<<1;
1.2003 + TestResult = StaticExtension(aBusId, testId, NULL, NULL);
1.2004 + if(TestResult!=KErrNotReady) break;
1.2005 + }
1.2006 +
1.2007 + cb->Cancel();
1.2008 + delete cb;
1.2009 + delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
1.2010 + delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
1.2011 + delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
1.2012 + delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
1.2013 +
1.2014 + }
1.2015 + r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.2016 + return TestResult;
1.2017 + }
1.2018 +
1.2019 +TInt DChannelIicClient::ConstructTransactionOne(TIicBusTransaction*& aTrans)
1.2020 + {
1.2021 + // Transaction is to contain three transfers, with data defined by
1.2022 + // KTransOneTferOne[], KTransOneTferTwo[], KTransOneTferThree[]
1.2023 + buf1 = HBuf8::New(21);
1.2024 + buf2 = HBuf8::New(8);
1.2025 + buf3 = HBuf8::New(6);
1.2026 + tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
1.2027 + tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterRead,8,buf2);
1.2028 + tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
1.2029 + TInt r = CreateDefaultSpiBuf(spiHeader);
1.2030 + if((r != KErrNone)||(spiHeader == NULL)||(buf1 == NULL)||(buf2 == NULL)||(buf3 == NULL)||(tfer1 == NULL)||(tfer2 == NULL)||(tfer3 == NULL))
1.2031 + {
1.2032 + CLIENT_PRINT(("DChannelIicClient::ConstructTransactionOne ERROR - failed to allocate the necessary memory\n"));
1.2033 + delete buf1;
1.2034 + delete buf2;
1.2035 + delete buf3;
1.2036 + delete tfer1;
1.2037 + delete tfer2;
1.2038 + delete tfer3;
1.2039 + delete spiHeader;
1.2040 + delete aTrans;
1.2041 + return KErrNoMemory;
1.2042 + }
1.2043 + aTrans = new TIicBusTransaction(spiHeader,tfer1);
1.2044 + buf1->Copy(&(KTransOneTferOne[0]),21);
1.2045 + buf2->Copy(&(KTransOneTferTwo[0]),8);
1.2046 + buf3->Copy(&(KTransOneTferThree[0]),6);
1.2047 + tfer1->LinkAfter(tfer2);
1.2048 + tfer2->LinkAfter(tfer3);
1.2049 + return KErrNone;
1.2050 + }
1.2051 +
1.2052 +void DChannelIicClient::CleanupTransactionOne(TIicBusTransaction*& aTrans)
1.2053 + {
1.2054 + // Release the allocated memory
1.2055 + delete buf1;
1.2056 + buf1=NULL;
1.2057 + delete buf2;
1.2058 + buf2=NULL;
1.2059 + delete buf3;
1.2060 + buf3=NULL;
1.2061 + delete tfer1;
1.2062 + tfer1=NULL;
1.2063 + delete tfer2;
1.2064 + tfer2=NULL;
1.2065 + delete tfer3;
1.2066 + tfer3=NULL;
1.2067 + delete spiHeader;
1.2068 + spiHeader=NULL;
1.2069 + delete aTrans;
1.2070 + aTrans=NULL;
1.2071 + }
1.2072 +
1.2073 +
1.2074 +void DChannelIicClient::CleanupTransaction(TIicBusTransaction*& aTrans)
1.2075 + {
1.2076 + delete iSpiBuf;
1.2077 + iSpiBuf=NULL;
1.2078 + delete iI2cBuf;
1.2079 + iI2cBuf=NULL;
1.2080 + TIicBusTransfer* currTfer = iTfer;
1.2081 + TIicBusTransfer* nextTfer = NULL;
1.2082 + while(currTfer)
1.2083 + {
1.2084 + TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
1.2085 + delete currTfer;
1.2086 + if(nextTfer)
1.2087 + currTfer = nextTfer;
1.2088 + else
1.2089 + currTfer = NULL;
1.2090 + };
1.2091 + iTfer=NULL;
1.2092 + currTfer = iFdTfer;
1.2093 + nextTfer = NULL;
1.2094 + while(currTfer)
1.2095 + {
1.2096 + TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
1.2097 + delete currTfer;
1.2098 + if(nextTfer)
1.2099 + currTfer = nextTfer;
1.2100 + else
1.2101 + currTfer = NULL;
1.2102 + };
1.2103 + iFdTfer=NULL;
1.2104 + if(aTrans!=NULL)
1.2105 + {
1.2106 + delete aTrans;
1.2107 + aTrans=NULL;
1.2108 + }
1.2109 + if(iTransPreamble!=NULL)
1.2110 + {
1.2111 + delete iTransPreamble;
1.2112 + iTransPreamble=NULL;
1.2113 + }
1.2114 + }
1.2115 +
1.2116 +void DChannelIicClient::TransModifCallback(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt aResult, TAny* aParam)
1.2117 + {
1.2118 + // Callback function used to test re-use of transaction and transfer buffers
1.2119 + // aParam is the address of the simulated client driver
1.2120 + DChannelIicClient* channel = (DChannelIicClient*)aParam;
1.2121 + TTransBufReuseData* reuseData = &(channel->iTransBufReuseData);
1.2122 +
1.2123 + // Since the transaction is no longer queued, should be able to modify the transfer and transaction content
1.2124 + channel->TestTransModification(reuseData->iTransaction, reuseData->iHdTfer, reuseData->iFdTfer, reuseData->iHdr);
1.2125 +
1.2126 + // Complete the user's request, delete objects allocated for this test and return
1.2127 + Kern::RequestComplete(channel->iClient, channel->iStatus, aResult);
1.2128 + delete reuseData->iCallback; // Must do this before deleting the Transaction, in CleanupTransaction
1.2129 + channel->CleanupTransaction(channel->iTrans);
1.2130 + return;
1.2131 + }
1.2132 +
1.2133 +
1.2134 +void DChannelIicClient::TestTransModification(TIicBusTransaction* aTransaction,
1.2135 + TIicBusTransfer* aHdTfer,
1.2136 + TIicBusTransfer* aFdTfer,
1.2137 + TDes8* aHdr)
1.2138 + {
1.2139 + // Function to test that the content of Transaction and Transfer objects can be modified
1.2140 + // This assumes that the Transaction is in the appropriate state (EFree) - otherwise, the code will assert
1.2141 + // This function also assumes that transaction has aleady added the half-duplex and full-duplex transfers
1.2142 + // that are passed in as arguments, and that the transfers lists are non-NULL
1.2143 + // The original type of the transfers (read, write) are ignored, since it is not of interest in this test -
1.2144 + // instead, what is important is to ensure that the half-duplex and full-duplex transfer types are in opposing
1.2145 + // directions - so the types are explicitly set in this test.
1.2146 + //
1.2147 + TDes8* origBuf = NULL;
1.2148 + TInt8 origGranularity = 0;
1.2149 +
1.2150 + // Create a buffer for use in this function
1.2151 + _LIT(temporaryText,"Temporary Text");
1.2152 + TBuf8<15> tempBuf_8;
1.2153 + tempBuf_8.Copy(temporaryText);
1.2154 +
1.2155 + // Test modification of the two transfer lists while still part of the transaction
1.2156 + origBuf = (TDes8*)(aHdTfer->GetBuffer());
1.2157 + origGranularity = aHdTfer->WordWidth();
1.2158 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
1.2159 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
1.2160 +
1.2161 + origBuf = (TDes8*)(aFdTfer->GetBuffer());
1.2162 + origGranularity = aFdTfer->WordWidth();
1.2163 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
1.2164 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
1.2165 +
1.2166 + // Test transfers can be removed from the transaction
1.2167 + aTransaction->RemoveHalfDuplexTrans();
1.2168 + aTransaction->RemoveFullDuplexTrans();
1.2169 +
1.2170 + // Test modification of the two transfer lists while not part of a transaction
1.2171 + origBuf = (TDes8*)(aHdTfer->GetBuffer());
1.2172 + origGranularity = aHdTfer->WordWidth();
1.2173 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
1.2174 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
1.2175 +
1.2176 + origBuf = (TDes8*)(aFdTfer->GetBuffer());
1.2177 + origGranularity = aFdTfer->WordWidth();
1.2178 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
1.2179 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
1.2180 +
1.2181 + // Test transfers can be re-added to the transaction
1.2182 + aTransaction->SetHalfDuplexTrans(aHdr,aHdTfer);
1.2183 + aTransaction->SetFullDuplexTrans(aFdTfer);
1.2184 +
1.2185 + // Test modification of the two transfer lists now re-added to the transaction
1.2186 + origBuf = (TDes8*)(aHdTfer->GetBuffer());
1.2187 + origGranularity = aHdTfer->WordWidth();
1.2188 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
1.2189 + aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
1.2190 +
1.2191 + origBuf = (TDes8*)(aFdTfer->GetBuffer());
1.2192 + origGranularity = aFdTfer->WordWidth();
1.2193 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
1.2194 + aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
1.2195 +
1.2196 + return;
1.2197 + }
1.2198 +
1.2199 +TInt DChannelIicClient::DoControl(TInt aId, TAny* a1, TAny* a2)
1.2200 + {
1.2201 + CLIENT_PRINT(("DChannelIicClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
1.2202 + TInt r=KErrNone;
1.2203 + // To support testing, any values of aId for StaticExtension must be shifted left one place
1.2204 + // and for a Slave tests, the two msbs must be zero
1.2205 + TInt ctrlIoVal = 0;
1.2206 + if((aId & KTestMasterControlIo) == KTestMasterControlIo)
1.2207 + ctrlIoVal = (aId << 1);
1.2208 + if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
1.2209 + ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
1.2210 + switch(aId)
1.2211 + {
1.2212 + case(RBusDevIicClient::EQTransSync):
1.2213 + {
1.2214 + // a1 specifies Bus Realisation Config to use
1.2215 + // a2 is a pointer to TUsideTracnDesc
1.2216 + TIicBusTransaction* trans = NULL;
1.2217 + TIicBusTransfer* tfer = NULL;
1.2218 + TConfigSpiBufV01 *spiBuf = NULL;
1.2219 +
1.2220 + //Read the transaction header to determin if it is a multi-transaction type
1.2221 + TUsideTracnDesc usTrans;
1.2222 +
1.2223 + if((Kern::ThreadRawRead(iClient,a2,&usTrans,sizeof(TUsideTracnDesc)))!=KErrNone)
1.2224 + {
1.2225 + CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
1.2226 + return KErrGeneral;
1.2227 + }
1.2228 +
1.2229 + if((usTrans.iFlags)&KTransactionWithMultiTransc)
1.2230 + {
1.2231 + // Since we are testing a multi-transaction, create another transaction object iMultiTransac,
1.2232 + // to represent the delayed part of the multi-transaction. After the preliminary
1.2233 + // transaction(passed from t_iic, with one read transfer) has been performed,
1.2234 + // the IIC code will find that it is part of a
1.2235 + // multi-transaction; it will call the callback for the transaction(set as MultiTranscCallbackFunc,
1.2236 + // in ExtractTransData) and this will return a pointer to the next part of the multi-transaction
1.2237 + // to be performed(iMultiTransac). It will then immediately pass this transaction object
1.2238 + // to the PSL for processing - before considering any other transactions that have been
1.2239 + // requested, and without completing the multi-transaction request(this is done once
1.2240 + // iMultiTransac has been processed)
1.2241 + buf1 = HBuf8::New(1);
1.2242 + spiBuf = new TConfigSpiBufV01();
1.2243 + if(buf1 == NULL||spiBuf == NULL) {delete buf1;delete spiBuf; return KErrNoMemory;}
1.2244 +
1.2245 +
1.2246 + if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
1.2247 + {
1.2248 + CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
1.2249 + return KErrGeneral;
1.2250 + }
1.2251 +
1.2252 + tfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
1.2253 + if(tfer == NULL) {delete buf1; delete spiBuf; return KErrNoMemory;}
1.2254 +
1.2255 + iMultiTransac = new TIicBusTransaction((TDes8*)spiBuf, tfer);
1.2256 + if(iMultiTransac == NULL) {delete buf1; delete spiBuf; delete tfer; return KErrNoMemory;}
1.2257 + }
1.2258 + r = ExtractTransData((TUsideTracnDesc*)a2, trans);
1.2259 + if(r!=KErrNone)
1.2260 + {
1.2261 + CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - ExtractTransData returned %d\n",r));
1.2262 + return r;
1.2263 + }
1.2264 + CLIENT_PRINT(("DChannelIicClient::DoControl invoking (synchronous) QueueTransaction with busId=0x%x, trans=0x%x\n",(TUint32)a1,trans));
1.2265 +
1.2266 + r = QueueTransaction((TUint32)a1, trans);
1.2267 + CleanupExtractTrans(trans);
1.2268 + CleanupTransaction(trans);
1.2269 + if((usTrans.iFlags)&KTransactionWithMultiTransc)
1.2270 + {
1.2271 + delete buf1;
1.2272 + delete spiBuf;
1.2273 + delete tfer;
1.2274 + delete iMultiTransac;
1.2275 + }
1.2276 + break;
1.2277 + }
1.2278 + case(RBusDevIicClient::ECtlIoBlockReqCompletion):
1.2279 + case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
1.2280 + case(RBusDevIicClient::ECtlIoDeRegChan):
1.2281 + {
1.2282 + // a1 specifies Bus Realisation Config to use
1.2283 + CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
1.2284 + // Use the IIC StaticExtension interface to pass the request to the bus implementation
1.2285 + r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
1.2286 + break;
1.2287 + }
1.2288 + case(RBusDevIicClient::ECtlIoTestFullDuplexTrans):
1.2289 + {
1.2290 + // a1 specifies Bus Realisation Config to use
1.2291 + CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
1.2292 + r = DoCreateFullDuplexTransTest((TInt)a2);
1.2293 + break;
1.2294 + }
1.2295 + case(RBusDevIicClient::ECtlIoPriorityTest):
1.2296 + {
1.2297 + // a1 specifies Bus Realisation Config to use
1.2298 + CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
1.2299 + r = DoPriorityTest((TUint32)a1);
1.2300 + break;
1.2301 + }
1.2302 +
1.2303 + case(RBusDevIicClient::ECtlIoTracnOne):
1.2304 + {
1.2305 + // a1 specifies Bus Realisation Config to use
1.2306 + CLIENT_PRINT(("DChannelIicClient::StaticExtension invoking StaticExtension with ctrlIoVal=%d, busId=0x%x\n",aId,(TUint32)a1));
1.2307 + // Use the IIC StaticExtension interface to pass the request to the bus implementation
1.2308 + r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
1.2309 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("StaticExtension",__LINE__));
1.2310 + if(r == KErrNone)
1.2311 + {
1.2312 + // Create then send (synchronously) Transaction One
1.2313 + r = ConstructTransactionOne(iTrans);
1.2314 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.2315 + r = QueueTransaction((TUint32)a1, iTrans);
1.2316 + __ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
1.2317 + CleanupTransactionOne(iTrans);
1.2318 + }
1.2319 + r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.2320 + break;
1.2321 + }
1.2322 + case(RBusDevIicClient::ECtlIoSetTimeOutFlag):
1.2323 + {
1.2324 + CLIENT_PRINT(("DChannelIicClient::DoControl instruct the bus that it is to simulate a slave timeout"));
1.2325 + // To support testing, function index passed to StaticExtension must be shifted one place to the left
1.2326 + TUint testIndex = ((TUint)RBusDevIicClient::ECtlIoSetTimeOutFlag)<<1;;
1.2327 + r = StaticExtension((TUint32)a1, testIndex, NULL, NULL);
1.2328 + break;
1.2329 + }
1.2330 + case(RBusDevIicClient::ECtlIoNone):
1.2331 + {
1.2332 + CLIENT_PRINT(("DChannelIicClient::DoControl Return the bus to its default test state"));
1.2333 + r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
1.2334 + break;
1.2335 + }
1.2336 +
1.2337 +// Support for MasterSlave processing
1.2338 +
1.2339 + case(RBusDevIicClient::ECaptureChanSync):
1.2340 + {
1.2341 + // a1 is a pointer to the TDes8* aConfigHdr
1.2342 + // a2 is a pointer to TInt* parms[2], where:
1.2343 + // parms[0]=(TInt*)aBusId;
1.2344 + // parms[1]=&aChannelId;
1.2345 + //
1.2346 + TInt* parms[2];
1.2347 + r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
1.2348 + if(r!=KErrNone)
1.2349 + break; // Can't proceed if can't access request parameters
1.2350 + //
1.2351 + TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
1.2352 + CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
1.2353 + if (hdrSize<=0)
1.2354 + {
1.2355 + CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
1.2356 + return KErrArgument;
1.2357 + }
1.2358 + if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
1.2359 + return KErrNoMemory;
1.2360 + r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
1.2361 + if(r!=KErrNone)
1.2362 + {
1.2363 + delete iConfigHdr;
1.2364 + return r;
1.2365 + }
1.2366 + // Store the address of the user-side variable to update with the ChannelId
1.2367 + iClientChanId=parms[1];
1.2368 +
1.2369 + CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
1.2370 + r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
1.2371 + if(r != KErrNone)
1.2372 + delete iConfigHdr;
1.2373 + CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
1.2374 +
1.2375 + TInt r=Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
1.2376 + (void)r; // Silence the compiler
1.2377 +
1.2378 + break;
1.2379 + }
1.2380 +
1.2381 + case(RBusDevIicClient::EReleaseChan):
1.2382 + {
1.2383 + // a1 represents TInt aChannelId
1.2384 + CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
1.2385 + r = ReleaseChannel((TInt)a1);
1.2386 + delete iConfigHdr;
1.2387 + break;
1.2388 + }
1.2389 +
1.2390 + case(RBusDevIicClient::EInitSlaveClient):
1.2391 + {
1.2392 + r=InitSlaveClient();
1.2393 + break;
1.2394 + }
1.2395 +
1.2396 +#ifdef STANDALONE_CHANNEL
1.2397 + case(RBusDevIicClient::ETestIicChannelInlineFunc):
1.2398 + {
1.2399 + TTestIicChannelInterface channelInterface(DIicBusChannel::EMaster, DIicBusChannel::EI2c, DIicBusChannel::EHalfDuplex);
1.2400 + r = channelInterface.TestInterface();
1.2401 + break;
1.2402 + }
1.2403 +#endif
1.2404 +
1.2405 + default:
1.2406 + {
1.2407 + CLIENT_PRINT(("DChannelIicClient::DoControl - unrecognised value for aId=0x%x\n",aId));
1.2408 + r=KErrArgument;
1.2409 + break;
1.2410 + }
1.2411 + }
1.2412 + return r;
1.2413 + }
1.2414 +
1.2415 +TInt DChannelIicClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.2416 + {
1.2417 + CLIENT_PRINT(("DChannelIicClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
1.2418 +
1.2419 + TInt r=KErrNone;
1.2420 + switch(aId)
1.2421 + {
1.2422 + case(RBusDevIicClient::EQTransAsync):
1.2423 + {
1.2424 + // a1 specifies Bus Realisation Config to use
1.2425 + // a2 is a pointer to TIicBusTransaction
1.2426 + TIicBusTransaction* trans = NULL;
1.2427 + r = ExtractTransData((TUsideTracnDesc*)a2, trans);
1.2428 + if(r!=KErrNone)
1.2429 + {
1.2430 + CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - ExtractTransData returned %d\n",r));
1.2431 + return r;
1.2432 + }
1.2433 + // Create TIicBusCallback object
1.2434 + TIicBusCallback* cb = new TIicBusCallback(AsyncCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
1.2435 + TTransCbPair* cbPair = new TTransCbPair();
1.2436 + cbPair->iCb=cb;
1.2437 + cbPair->iTrans=trans;
1.2438 + // Create an entry in the RPointerArray for TRequestStatus - TIicBusTransaction pairs
1.2439 + TTransStatusPair* pair = new TTransStatusPair();
1.2440 + pair->iReq=aStatus;
1.2441 + pair->iTrans=trans;
1.2442 + r=InsertPairs(pair,cbPair);
1.2443 + if(r!=KErrNone)
1.2444 + {
1.2445 + CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - InsertInOrder returned %d\n",r));
1.2446 + return r;
1.2447 + }
1.2448 + CLIENT_PRINT(("DChannelIicClient::DoRequest invoking (asynchronous) QueueTransaction with busId=0x%x, trans=0x%x, cb=0x%x\n",(TUint32)a1,trans,cb));
1.2449 + r = QueueTransaction((TUint32)a1, trans, cb);
1.2450 + if(r!=KErrNone)
1.2451 + {
1.2452 + // The transaction was not queued - since it will not be completed asynchronously, need to remove it here
1.2453 + GetWriteAccess();
1.2454 + Lock();
1.2455 + TInt pairIndex=iTransStatArrayByTrans.FindInOrder(pair,TransStatusOrderByTrans);
1.2456 + __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByTrans pairIndex<0",__LINE__));
1.2457 + iTransStatArrayByTrans.Remove(pairIndex);
1.2458 + pairIndex = iTransStatArrayByStatus.FindInOrder(pair,TransStatusOrderByStatus);
1.2459 + __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByStatus pairIndex<0",__LINE__));
1.2460 + iTransStatArrayByStatus.Remove(pairIndex);
1.2461 + pairIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
1.2462 + __ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync Cb by Trans pairIndex<0",__LINE__));
1.2463 + iTransCbArrayByTrans.Remove(pairIndex);
1.2464 + FreeWriteAccess();
1.2465 + Unlock();
1.2466 + Kern::RequestComplete(iClient, aStatus, r);
1.2467 + delete cb;
1.2468 + delete cbPair;
1.2469 + CleanupExtractTrans(pair->iTrans);
1.2470 + CleanupTransaction(pair->iTrans);
1.2471 + delete pair;
1.2472 + }
1.2473 + break;
1.2474 + }
1.2475 +
1.2476 + case(RBusDevIicClient::ECtrlIoTestBufReUse):
1.2477 + {
1.2478 + iStatus = aStatus;
1.2479 + // a1 specifies Bus Realisation Config to use
1.2480 +
1.2481 + // Ensure object pointers are made available
1.2482 + CleanupTransaction(iTrans);
1.2483 +
1.2484 + TInt r = KErrNone;
1.2485 + TIicBusCallback* cb = NULL;
1.2486 +
1.2487 + // Use default constructor to create an empty transaction
1.2488 + iTrans = new TIicBusTransaction();
1.2489 + if(iTrans == NULL)
1.2490 + {
1.2491 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTrans=NULL\n"));
1.2492 + r = KErrNoMemory;
1.2493 + }
1.2494 +
1.2495 + // Create a header for the transaction
1.2496 + if(r == KErrNone)
1.2497 + {
1.2498 + r = CreateDefaultSpiBuf(iSpiBuf);
1.2499 + if(r != KErrNone)
1.2500 + {
1.2501 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - CreateDefaultSpiBuf returned %d\n",r));
1.2502 + }
1.2503 + }
1.2504 +
1.2505 + // Create and add transfer lists for half-duplex and full-duplex entries in the transaction
1.2506 + if(r == KErrNone)
1.2507 + {
1.2508 + // Use simple text as payload, 8bit granularity, half-duplex write, full-duplex read (ie payload ignored)
1.2509 + _LIT(halfDuplexText1,"Half Duplex Text 1");
1.2510 + TBuf8<19> halfDuplexBuf_8;
1.2511 + halfDuplexBuf_8.Copy(halfDuplexText1);
1.2512 + iTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf_8);
1.2513 + if(iTfer == NULL)
1.2514 + {
1.2515 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTfer=NULL\n"));
1.2516 + r = KErrNoMemory;
1.2517 + }
1.2518 + else
1.2519 + {
1.2520 + _LIT(halfDuplexText2,"Half Duplex Text 2");
1.2521 + TBuf8<19> halfDuplexBuf2_8;
1.2522 + halfDuplexBuf2_8.Copy(halfDuplexText2);
1.2523 + TIicBusTransfer* tempHdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf2_8);
1.2524 + if(tempHdTfer == NULL)
1.2525 + {
1.2526 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempHdTfer=NULL\n"));
1.2527 + r = KErrNoMemory;
1.2528 + }
1.2529 + else
1.2530 + {
1.2531 + iTfer->LinkAfter(tempHdTfer);
1.2532 + }
1.2533 + }
1.2534 + if(r == KErrNone)
1.2535 + {
1.2536 + _LIT(fullDuplexText1,"Full Duplex Text 1");
1.2537 + TBuf8<19> fullDuplexBuf1_8;
1.2538 + fullDuplexBuf1_8.Copy(fullDuplexText1);
1.2539 + iFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf1_8);
1.2540 + if(iFdTfer == NULL)
1.2541 + {
1.2542 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iFdTfer=NULL\n"));
1.2543 + r = KErrNoMemory;
1.2544 + }
1.2545 + else
1.2546 + {
1.2547 + _LIT(fullDuplexText2,"Full Duplex Text 2");
1.2548 + TBuf8<19> fullDuplexBuf2_8;
1.2549 + fullDuplexBuf2_8.Copy(fullDuplexText2);
1.2550 + TIicBusTransfer* tempFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf2_8);
1.2551 + if(tempFdTfer == NULL)
1.2552 + {
1.2553 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempFdTfer=NULL\n"));
1.2554 + r = KErrNoMemory;
1.2555 + }
1.2556 + else
1.2557 + {
1.2558 + iFdTfer->LinkAfter(tempFdTfer);
1.2559 + }
1.2560 + }
1.2561 + }
1.2562 + }
1.2563 +
1.2564 + // Add the Header and Transfers to the Transaction
1.2565 + if(r == KErrNone)
1.2566 + r = iTrans->SetHalfDuplexTrans(iSpiBuf, iTfer);
1.2567 + if(r != KErrNone)
1.2568 + {
1.2569 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetHalfDuplexTrans returned %d\n",r));
1.2570 + }
1.2571 +
1.2572 + if(r == KErrNone)
1.2573 + r = iTrans->SetFullDuplexTrans(iFdTfer);
1.2574 + if(r != KErrNone)
1.2575 + {
1.2576 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetFullDuplexTrans returned %d\n",r));
1.2577 + }
1.2578 +
1.2579 + // Specify the callback object to use
1.2580 + if(r == KErrNone)
1.2581 + {
1.2582 + cb = new TIicBusCallback(TransModifCallback, this, iDfcQue, 5); // 5 arbitrary
1.2583 + if(cb == NULL)
1.2584 + {
1.2585 + CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - cb=NULL\n"));
1.2586 + r = KErrNoMemory;
1.2587 + }
1.2588 + }
1.2589 +
1.2590 + // Since the transaction is not yet queued, should be able to modify the transfer and transaction content
1.2591 + TestTransModification(iTrans, iTfer, iFdTfer, iSpiBuf);
1.2592 +
1.2593 + // Store the relevant data in this object's iTransBufReuseData member
1.2594 + iTransBufReuseData.iTransaction = iTrans;
1.2595 + iTransBufReuseData.iHdTfer = iTfer;
1.2596 + iTransBufReuseData.iFdTfer = iFdTfer;
1.2597 + iTransBufReuseData.iHdr = iSpiBuf;
1.2598 + iTransBufReuseData.iCallback = cb;
1.2599 +
1.2600 + // Now queue the transaction. The callback function will re-apply the modification tests and delete the
1.2601 + // objects created here
1.2602 + // If the queueing fails, complete the test here and clean up
1.2603 + r = QueueTransaction((TInt)a1, iTrans, cb);
1.2604 + if(r != KErrNone)
1.2605 + {
1.2606 + Kern::RequestComplete(iClient, iStatus, r);
1.2607 + delete iTransBufReuseData.iCallback; // Must do this before deleting the Transaction in CleanupTransaction
1.2608 + CleanupTransaction(iTrans);
1.2609 + }
1.2610 + break;
1.2611 + }
1.2612 + default:
1.2613 + {
1.2614 + CLIENT_PRINT(("DChannelIicClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
1.2615 + r=KErrArgument;
1.2616 + break;
1.2617 + }
1.2618 + }
1.2619 + return r;
1.2620 + }
1.2621 +
1.2622 +
1.2623 +// Support for MasterSlave processing
1.2624 +static void MsSlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny* aParam)
1.2625 + {
1.2626 + CLIENT_PRINT(("> MsSlaveClientCallbackFunc() - aChannelId=0x%x,aReturn=%d,aTrigger=0x%x,aRxWords=0x%x,aTxWords=0x%x,aParam=0x%x\n",aChannelId,aReturn,aTrigger,aRxWords,aTxWords,aParam));
1.2627 + (void)aTxWords; // Unused if CLIENT_PRINT is disabled
1.2628 + (void)aRxWords; // Unused if CLIENT_PRINT is disabled
1.2629 + DChannelIicClient* channel = (DChannelIicClient*)aParam;
1.2630 + CLIENT_PRINT(("MsSlaveClientCallbackFunc() - channel=0x%x\n",channel));
1.2631 + if(aTrigger == EAsyncCaptChan)
1.2632 + {
1.2633 + CLIENT_PRINT(("MsSlaveClientCallbackFunc: capture channel completed\n"));
1.2634 + // Set iChannelId, and write to user-side variable.
1.2635 + channel->iChannelId=aChannelId;
1.2636 + TInt r=Kern::ThreadRawWrite(channel->iClient,channel->iClientChanId,&aChannelId,sizeof(TInt));
1.2637 + if(r == KErrNone)
1.2638 + r=aReturn;
1.2639 + channel->RequestComplete(r); // Inform user of error
1.2640 + return;
1.2641 + }
1.2642 + else
1.2643 + {
1.2644 + CLIENT_PRINT(("\nMsSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
1.2645 + channel->RequestComplete(aReturn); // Inform user of error
1.2646 + }
1.2647 + }
1.2648 +
1.2649 +void DChannelIicClient::RequestComplete(TInt r)
1.2650 + {
1.2651 + Kern::RequestComplete(iClient, iStatus, r);
1.2652 + }
1.2653 +
1.2654 +
1.2655 +TInt DChannelIicClient::InitSlaveClient()
1.2656 + {
1.2657 + iNotif = new TIicBusSlaveCallback(MsSlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
1.2658 + if(iNotif == NULL)
1.2659 + {
1.2660 + CLIENT_PRINT(("> DChannelIicClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
1.2661 + return KErrNoMemory;
1.2662 + }
1.2663 + return KErrNone;
1.2664 + }
1.2665 +