os/kernelhwsrv/kerneltest/e32test/iic/iic_psl/iic_client.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test/iic/iic_client.cpp
sl@0
    15
// Simulated (kernel-side) client of IIC Platform Independent Layer (PIL)
sl@0
    16
//
sl@0
    17
#include <kernel/kern_priv.h>		// for DThread, TDfc
sl@0
    18
#ifdef STANDALONE_CHANNEL
sl@0
    19
#include <drivers/iic_transaction.h>
sl@0
    20
#else
sl@0
    21
#include <drivers/iic.h>
sl@0
    22
#endif
sl@0
    23
#include "../t_iic.h"
sl@0
    24
#ifdef STANDALONE_CHANNEL
sl@0
    25
#include <drivers/iic_channel.h>
sl@0
    26
#include "i2c.h"
sl@0
    27
#include "spi.h"
sl@0
    28
#endif
sl@0
    29
sl@0
    30
#ifdef LOG_CLIENT
sl@0
    31
#define CLIENT_PRINT(str) Kern::Printf str
sl@0
    32
#else
sl@0
    33
#define CLIENT_PRINT(str)
sl@0
    34
#endif
sl@0
    35
sl@0
    36
const TInt KIicClientThreadPriority = 24;
sl@0
    37
const TInt KIicSlaveClientDfcPriority = 3; // 0 to 7, 7 is highest ... for MasterSlave functionality
sl@0
    38
sl@0
    39
const TInt KMaxNumChannels = 3;	// 1 SPI and 2 I2C
sl@0
    40
sl@0
    41
// Define an array of channel that the client is going to create.
sl@0
    42
// For iic_client, it needs SPI channels for Master tests, and I2c channels for MasterSlave tests.
sl@0
    43
#ifdef STANDALONE_CHANNEL
sl@0
    44
sl@0
    45
const TUint NUM_CHANNELS_SPI = 4; // Arbitrary
sl@0
    46
const TInt KChannelTypeArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMaster};
sl@0
    47
#define CHANNEL_TYPE_SPI(n) (KChannelTypeArraySpi[n])
sl@0
    48
const DIicBusChannel::TChannelDuplex KChannelDuplexArraySpi[NUM_CHANNELS_SPI] = {DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EHalfDuplex, DIicBusChannel::EFullDuplex};
sl@0
    49
#define CHANNEL_DUPLEX_SPI(n) (KChannelDuplexArraySpi[n])
sl@0
    50
#define BUS_TYPE_SPI (DIicBusChannel::ESpi)
sl@0
    51
sl@0
    52
#define NUM_CHANNELS_I2C 3
sl@0
    53
#if defined(MASTER_MODE) && !defined(SLAVE_MODE)
sl@0
    54
const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster};
sl@0
    55
#elif defined(MASTER_MODE) && defined(SLAVE_MODE)
sl@0
    56
const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave};
sl@0
    57
#else
sl@0
    58
const TInt KChannelTypeArrayI2c[NUM_CHANNELS_I2C] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave};
sl@0
    59
#endif
sl@0
    60
#define CHANNEL_TYPE_I2C(n) (KChannelTypeArrayI2c[n])
sl@0
    61
#define CHANNEL_DUPLEX_I2C(n) (DIicBusChannel::EHalfDuplex)
sl@0
    62
#define BUS_TYPE_I2C (DIicBusChannel::EI2c)
sl@0
    63
sl@0
    64
const TInt8 KSpiChannelNumBase = 1;	// Arbitrary, real platform may consult the Configuration Repository
sl@0
    65
									// Note limit of 5 bit representation (0-31)
sl@0
    66
sl@0
    67
LOCAL_C TInt8 AssignChanNumSpi()
sl@0
    68
	{
sl@0
    69
	static TInt8 iBaseChanNumSpi = KSpiChannelNumBase;
sl@0
    70
	CLIENT_PRINT(("SPI AssignChanNum - on entry, iBaseCanNum = 0x%x\n",iBaseChanNumSpi));
sl@0
    71
	return iBaseChanNumSpi++; // Arbitrary, for illustration
sl@0
    72
	}
sl@0
    73
sl@0
    74
#if defined(MASTER_MODE)
sl@0
    75
const TInt8 KI2cChannelNumBase = 10;	// Arbitrary, real platform may consult the Configuration Repository
sl@0
    76
										// Note limit of 5 bit representation (0-31)
sl@0
    77
sl@0
    78
#else
sl@0
    79
const TInt8 KI2cChannelNumBase = 10 + NUM_CHANNELS;	// For Slave mode, want to provide different response
sl@0
    80
													// If client assumes Master mode, should be informed not available
sl@0
    81
#endif
sl@0
    82
sl@0
    83
LOCAL_C TInt8 AssignChanNumI2c()
sl@0
    84
	{
sl@0
    85
	static TInt8 iBaseChanNumI2c = KI2cChannelNumBase;
sl@0
    86
	CLIENT_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNumI2c));
sl@0
    87
	return iBaseChanNumI2c++; // Arbitrary, for illustration
sl@0
    88
	}
sl@0
    89
sl@0
    90
class DIicClientChan : public DBase
sl@0
    91
	{
sl@0
    92
public:
sl@0
    93
	DIicClientChan(DIicBusChannel* aChan, TInt8 aChanNum, TUint8 aChanType):iChan(aChan),iChanNumber(aChanNum),iChanType(aChanType){};
sl@0
    94
	~DIicClientChan();
sl@0
    95
	TInt GetChanNum()const {return iChanNumber;};
sl@0
    96
	TUint8 GetChanType()const {return iChanType;};
sl@0
    97
	DIicBusChannel* GetChannelPtr(){return iChan;};
sl@0
    98
	inline DIicClientChan& operator=(DIicClientChan& aChan) {iChanNumber=aChan.iChanNumber; iChanType=aChan.iChanType; iChan=aChan.iChan; return *this;};
sl@0
    99
	inline TInt operator==(DIicClientChan& aChan) {if((iChanNumber == aChan.iChanNumber)&&(iChanType == aChan.iChanType)&&(iChan == aChan.iChan)) return 1;return 0;};
sl@0
   100
private:
sl@0
   101
	TInt iChanNumber;
sl@0
   102
	TUint8 iChanType;
sl@0
   103
	DIicBusChannel* iChan;
sl@0
   104
	};
sl@0
   105
sl@0
   106
DIicClientChan::~DIicClientChan()
sl@0
   107
	{
sl@0
   108
	delete iChan;
sl@0
   109
	}
sl@0
   110
sl@0
   111
#endif /*STANDALONE_CHANNEL*/
sl@0
   112
sl@0
   113
sl@0
   114
#ifdef STANDALONE_CHANNEL
sl@0
   115
_LIT(KLddRootName,"iic_client_ctrless");
sl@0
   116
#else
sl@0
   117
_LIT(KLddRootName,"iic_client");
sl@0
   118
#endif
sl@0
   119
_LIT(KIicClientThreadName,"IicClientLddThread");
sl@0
   120
sl@0
   121
struct TCapsIicClient
sl@0
   122
    {
sl@0
   123
    TVersion version;
sl@0
   124
    };
sl@0
   125
sl@0
   126
struct TTransStatusPair
sl@0
   127
	{
sl@0
   128
	TRequestStatus* iReq;
sl@0
   129
	TIicBusTransaction* iTrans;
sl@0
   130
	};
sl@0
   131
sl@0
   132
struct TTransCbPair
sl@0
   133
	{
sl@0
   134
	TIicBusTransaction* iTrans;
sl@0
   135
	TIicBusCallback* iCb;
sl@0
   136
	};
sl@0
   137
sl@0
   138
struct TExtractInfo
sl@0
   139
    {
sl@0
   140
    TExtractInfo(){iBufPtr = NULL; iTfer = NULL;}
sl@0
   141
    ~TExtractInfo(){delete iBufPtr; delete iTfer;}
sl@0
   142
    TDes8* iBufPtr;
sl@0
   143
    TIicBusTransfer* iTfer;
sl@0
   144
    TIicBusTransaction* iTrans;
sl@0
   145
    };
sl@0
   146
sl@0
   147
struct TTransBufReuseData
sl@0
   148
	{
sl@0
   149
	// Convenience for testing, only - retain pointers to private data
sl@0
   150
	// so that it can be re-used from a callback.
sl@0
   151
	TIicBusTransaction* iTransaction;
sl@0
   152
	TIicBusTransfer* iHdTfer;
sl@0
   153
	TIicBusTransfer* iFdTfer;
sl@0
   154
	TDes8* iHdr;
sl@0
   155
	// Pointer to callback object (for cleanup)
sl@0
   156
	TIicBusCallback* iCallback;
sl@0
   157
	};
sl@0
   158
sl@0
   159
class DDeviceIicClient : public DLogicalDevice
sl@0
   160
    {
sl@0
   161
    public:
sl@0
   162
    /**
sl@0
   163
     * The constructor
sl@0
   164
     */
sl@0
   165
    DDeviceIicClient();
sl@0
   166
    /**
sl@0
   167
     * The destructor
sl@0
   168
     */
sl@0
   169
    ~DDeviceIicClient();
sl@0
   170
    /**
sl@0
   171
     * Second stage constructor - install the device
sl@0
   172
     */
sl@0
   173
    virtual TInt Install();
sl@0
   174
    /**
sl@0
   175
     * Get the Capabilites of the device
sl@0
   176
     * @param aDes descriptor that will contain the returned capibilites
sl@0
   177
     */
sl@0
   178
    virtual void GetCaps(TDes8 &aDes) const;
sl@0
   179
    /**
sl@0
   180
     * Create a logical channel to the device
sl@0
   181
     */
sl@0
   182
    virtual TInt Create(DLogicalChannelBase*& aChannel);
sl@0
   183
sl@0
   184
	public:
sl@0
   185
    };
sl@0
   186
sl@0
   187
#ifdef STANDALONE_CHANNEL
sl@0
   188
/*This class is used to test the set and get inline functions
sl@0
   189
 *  of DIicBusChannel Interface.
sl@0
   190
 * */
sl@0
   191
class TTestIicChannelInterface: public DIicBusChannel
sl@0
   192
{
sl@0
   193
public:
sl@0
   194
    TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex);
sl@0
   195
    ~TTestIicChannelInterface(){};
sl@0
   196
    TInt DoCreate(){return 0;};
sl@0
   197
    TInt CheckHdr(TDes8* /*aHdr*/){return 0;};
sl@0
   198
    TInt TestInterface();
sl@0
   199
private:
sl@0
   200
    TBool TestChannelType(DIicBusChannel::TChannelType aType );
sl@0
   201
    TBool TestBusType(DIicBusChannel::TBusType aType );
sl@0
   202
    TBool TestDuplexType(DIicBusChannel::TChannelDuplex aType );
sl@0
   203
};
sl@0
   204
sl@0
   205
TTestIicChannelInterface::TTestIicChannelInterface(TChannelType aChannelType, TBusType aBusType, TChannelDuplex aChanDuplex)
sl@0
   206
        : DIicBusChannel(aChannelType, aBusType, aChanDuplex)
sl@0
   207
    {}
sl@0
   208
sl@0
   209
TBool TTestIicChannelInterface::TestChannelType(DIicBusChannel::TChannelType aType)
sl@0
   210
    {
sl@0
   211
    CLIENT_PRINT(("Setting channel type 0x%x\n", aType));
sl@0
   212
    SetChannelType(aType);
sl@0
   213
    if(aType != ChannelType())
sl@0
   214
        {
sl@0
   215
        CLIENT_PRINT(("ERROR: Mismatch, looking for channel 0x%x but found 0x%x\n", aType, ChannelType()));
sl@0
   216
        return EFalse;
sl@0
   217
        }
sl@0
   218
    else
sl@0
   219
        {
sl@0
   220
        CLIENT_PRINT(("Looking for channel 0x%x and found 0x%x\n", aType, ChannelType()));
sl@0
   221
        }
sl@0
   222
    return ETrue;
sl@0
   223
    }
sl@0
   224
sl@0
   225
TBool TTestIicChannelInterface::TestBusType(DIicBusChannel::TBusType aType)
sl@0
   226
    {
sl@0
   227
    CLIENT_PRINT(("Setting Bus type 0x%x\n", aType));
sl@0
   228
    SetBusType(aType);
sl@0
   229
    if(aType != BusType())
sl@0
   230
        {
sl@0
   231
        CLIENT_PRINT(("ERROR: Mismatch, looking for Bus 0x%x but found 0x%x\n", aType, BusType()));
sl@0
   232
        return EFalse;
sl@0
   233
        }
sl@0
   234
    else
sl@0
   235
        {
sl@0
   236
        CLIENT_PRINT(("Looking for Bus 0x%x and found 0x%x\n", aType, BusType()));
sl@0
   237
        }    
sl@0
   238
    return ETrue;   
sl@0
   239
    }
sl@0
   240
sl@0
   241
TBool TTestIicChannelInterface::TestDuplexType(DIicBusChannel::TChannelDuplex aType)
sl@0
   242
    {
sl@0
   243
    CLIENT_PRINT(("Setting duplex channel type 0x%x\n", aType));
sl@0
   244
    SetChannelType(aType);
sl@0
   245
    if(aType != ChannelDuplex())
sl@0
   246
        {
sl@0
   247
        CLIENT_PRINT(("ERROR: Mismatch, looking for duplex channel 0x%x but found 0x%x\n", aType, ChannelDuplex()));
sl@0
   248
        return EFalse;
sl@0
   249
        }
sl@0
   250
    else
sl@0
   251
        {
sl@0
   252
        CLIENT_PRINT(("Looking for Duplex Channel 0x%x and found 0x%x\n", aType, ChannelDuplex()));
sl@0
   253
        }    
sl@0
   254
    return ETrue;   
sl@0
   255
    }
sl@0
   256
sl@0
   257
TInt TTestIicChannelInterface::TestInterface()
sl@0
   258
    {
sl@0
   259
    
sl@0
   260
    RArray <DIicBusChannel::TChannelType> chtype;
sl@0
   261
    RArray <DIicBusChannel::TBusType> bustype;
sl@0
   262
    RArray <DIicBusChannel::TChannelDuplex> dutype;
sl@0
   263
sl@0
   264
    chtype.Append(DIicBusChannel::EMaster);
sl@0
   265
    chtype.Append(DIicBusChannel::ESlave);
sl@0
   266
    chtype.Append(DIicBusChannel::EMasterSlave);
sl@0
   267
    
sl@0
   268
    bustype.Append(DIicBusChannel::EI2c);
sl@0
   269
    bustype.Append(DIicBusChannel::ESpi);
sl@0
   270
    bustype.Append(DIicBusChannel::EMicrowire);
sl@0
   271
    bustype.Append(DIicBusChannel::ECci);
sl@0
   272
    bustype.Append(DIicBusChannel::ESccb);
sl@0
   273
    
sl@0
   274
    dutype.Append(DIicBusChannel::EHalfDuplex);
sl@0
   275
    dutype.Append(DIicBusChannel::EFullDuplex);
sl@0
   276
      
sl@0
   277
    int result = KErrNone;
sl@0
   278
    int count = chtype.Count();
sl@0
   279
    int i=0;
sl@0
   280
    
sl@0
   281
    CLIENT_PRINT(("\nCheck Master/Slave channel setting\n"));
sl@0
   282
    CLIENT_PRINT(("\nChannel MASK  = 0x%x\n", KChannelTypeMask));    
sl@0
   283
    for(i=0; i< count; ++i)
sl@0
   284
        {
sl@0
   285
        if(!TestChannelType(chtype[i]))
sl@0
   286
            {
sl@0
   287
            result = KErrGeneral;
sl@0
   288
            break;
sl@0
   289
            }
sl@0
   290
        }
sl@0
   291
    CLIENT_PRINT(("\nCheck Master/Slave channel setting from higher bit number to lower, reverse enum.\n"));
sl@0
   292
    for(i=count-1; i >= 0; --i)
sl@0
   293
        {
sl@0
   294
        if(!TestChannelType(chtype[i]))
sl@0
   295
            {
sl@0
   296
            result = KErrGeneral;
sl@0
   297
            break;
sl@0
   298
            }
sl@0
   299
        }
sl@0
   300
    
sl@0
   301
    CLIENT_PRINT(("\nCheck Channel Bus type settings\n"));
sl@0
   302
    CLIENT_PRINT(("\nBus MASK  = 0x%x\n", KBusTypeMask));     
sl@0
   303
    count = bustype.Count();    
sl@0
   304
    for(i=0; i< count; ++i)
sl@0
   305
        {
sl@0
   306
        if(!TestBusType(bustype[i]))
sl@0
   307
            {
sl@0
   308
            result = KErrGeneral;
sl@0
   309
            break;
sl@0
   310
            }
sl@0
   311
        }
sl@0
   312
    CLIENT_PRINT(("\nCheck Channel Bus type settings from higher bit number to lower, reverse enum.\n"));   
sl@0
   313
    for(i = count-1; i >= 0; --i)
sl@0
   314
        {
sl@0
   315
        if(!TestBusType(bustype[i]))
sl@0
   316
            {
sl@0
   317
            result = KErrGeneral;
sl@0
   318
            break;
sl@0
   319
            }
sl@0
   320
        }
sl@0
   321
    CLIENT_PRINT(("\nCheck Channel Duplex settings\n"));
sl@0
   322
    CLIENT_PRINT(("\nDuplex MASK  = 0x%x\n", KChannelDuplexMask));     
sl@0
   323
    count = dutype.Count();
sl@0
   324
    for(i=0; i < count; ++i)
sl@0
   325
        {
sl@0
   326
        if(!TestDuplexType(dutype[i]))
sl@0
   327
            {
sl@0
   328
            result = KErrGeneral;
sl@0
   329
            break;
sl@0
   330
            }
sl@0
   331
        }
sl@0
   332
    CLIENT_PRINT(("\nCheck Channel Duplex setting from higher bit number to lower, reverse enum.\n"));        
sl@0
   333
    for(i = count-1; i >= 0; --i)
sl@0
   334
        {
sl@0
   335
        if(!TestDuplexType(dutype[i]))
sl@0
   336
            {
sl@0
   337
            result = KErrGeneral;
sl@0
   338
            break;
sl@0
   339
            }
sl@0
   340
        }
sl@0
   341
    chtype.Close();
sl@0
   342
    dutype.Close();
sl@0
   343
    bustype.Close();
sl@0
   344
    return result;
sl@0
   345
    }
sl@0
   346
#endif //STANDALONE_CHANNEL
sl@0
   347
sl@0
   348
class DChannelIicClient : public DLogicalChannel
sl@0
   349
    {
sl@0
   350
    public:
sl@0
   351
    DChannelIicClient();
sl@0
   352
    ~DChannelIicClient();
sl@0
   353
sl@0
   354
	TInt CleanupExtractTrans(TIicBusTransaction *aTrans);
sl@0
   355
sl@0
   356
	TInt InitIicClient();
sl@0
   357
sl@0
   358
    virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
sl@0
   359
sl@0
   360
    protected:
sl@0
   361
    virtual void HandleMsg(TMessageBase* aMsg);	// Note: this is a pure virtual in DLogicalChannel
sl@0
   362
sl@0
   363
    void DoCancel(TInt aMask);	// Name for convenience!
sl@0
   364
	TInt DoControl(TInt aId, TAny* a1, TAny* a2); // Name for convenience!
sl@0
   365
    TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2); // Name for convenience!
sl@0
   366
sl@0
   367
	void TestTransModification(TIicBusTransaction* aTransaction, // public to be accessed by callback
sl@0
   368
							  TIicBusTransfer* aHdTfer,
sl@0
   369
							  TIicBusTransfer* aFdTfer,
sl@0
   370
							  TDes8* aHdr);
sl@0
   371
#ifdef STANDALONE_CHANNEL
sl@0
   372
    public:
sl@0
   373
    static TInt OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry);
sl@0
   374
#endif
sl@0
   375
	private:
sl@0
   376
	TInt ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans);
sl@0
   377
	TInt CreateTransferListHalfDuplex(
sl@0
   378
				TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
sl@0
   379
				TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
sl@0
   380
				TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
sl@0
   381
	TInt CreateTransferListFullDuplex(
sl@0
   382
				TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
sl@0
   383
				TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
sl@0
   384
				TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3);
sl@0
   385
sl@0
   386
sl@0
   387
	TInt DeleteFullDuplexTest(TIicBusTransaction *aTrans);
sl@0
   388
sl@0
   389
	TInt DoCreateFullDuplexTransTest(TInt aTestType);
sl@0
   390
sl@0
   391
	TInt DoPriorityTest(TInt aBusId);
sl@0
   392
	TInt ConstructTransactionOne(TIicBusTransaction*& aTrans);
sl@0
   393
	void CleanupTransactionOne(TIicBusTransaction*& aTrans);
sl@0
   394
sl@0
   395
sl@0
   396
	TInt InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair);
sl@0
   397
sl@0
   398
	TInt CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf);
sl@0
   399
sl@0
   400
	//Add new functions for controller-less mode
sl@0
   401
	TInt QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback=NULL);
sl@0
   402
	TInt CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction);
sl@0
   403
	TInt StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2);
sl@0
   404
	TInt CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch=NULL);
sl@0
   405
	TInt ReleaseChannel(TInt aChannelId);
sl@0
   406
	public:
sl@0
   407
	inline void Lock() {Kern::MutexWait(*iArrayMutex);}
sl@0
   408
	inline void Unlock() {Kern::MutexSignal(*iArrayMutex);}
sl@0
   409
	inline void GetWriteAccess() {Kern::SemaphoreWait(*iChanArrWrtSem);}	// aNTicks not specified = wait forever
sl@0
   410
	inline void FreeWriteAccess() {Kern::SemaphoreSignal(*iChanArrWrtSem);}
sl@0
   411
sl@0
   412
	void CleanupTransaction(TIicBusTransaction*& aTrans); // public for access by callback
sl@0
   413
sl@0
   414
	static TIicBusTransaction* MultiTranscCallbackFunc(TIicBusTransaction* aTrans, TAny* aParam);
sl@0
   415
sl@0
   416
	static void TransModifCallback(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam);
sl@0
   417
sl@0
   418
	private:
sl@0
   419
	TDynamicDfcQue* iDfcQue;
sl@0
   420
sl@0
   421
	DMutex* iArrayMutex;		// used to protect array of channels
sl@0
   422
	DSemaphore* iChanArrWrtSem;	// used to synchronise write access to iChannelArray
sl@0
   423
sl@0
   424
	// Used for Transaction One
sl@0
   425
	HBuf8* buf1;
sl@0
   426
	HBuf8* buf2;
sl@0
   427
	HBuf8* buf3;
sl@0
   428
	HBuf8* buf4;
sl@0
   429
	HBuf8* buf5;
sl@0
   430
	HBuf8* buf6;
sl@0
   431
	TIicBusTransfer* tfer1;
sl@0
   432
	TIicBusTransfer* tfer2;
sl@0
   433
	TIicBusTransfer* tfer3;
sl@0
   434
	TIicBusTransfer* tfer4;
sl@0
   435
	TIicBusTransfer* tfer5;
sl@0
   436
	TIicBusTransfer* tfer6;
sl@0
   437
	TIicBusTransfer* tfer7;
sl@0
   438
	HBuf8* header;
sl@0
   439
	HBuf8* header2;
sl@0
   440
	HBuf8* header3;
sl@0
   441
	HBuf8* header4;
sl@0
   442
	HBuf8* header5;
sl@0
   443
	HBuf8* headerBlock;
sl@0
   444
	TConfigSpiBufV01* spiHeader;
sl@0
   445
sl@0
   446
sl@0
   447
	static TIicBusTransaction* iMultiTransac;
sl@0
   448
sl@0
   449
	// Used for simple transactions
sl@0
   450
	TIicBusTransaction* iTrans;
sl@0
   451
	TConfigSpiBufV01* iSpiBuf;
sl@0
   452
	TConfigI2cBufV01* iI2cBuf;
sl@0
   453
	TIicBusTransfer* iTfer;
sl@0
   454
	TIicBusTransactionPreamble* iTransPreamble;
sl@0
   455
	TIicBusTransfer* iFdTfer;
sl@0
   456
sl@0
   457
	public:
sl@0
   458
	DThread* iClient;
sl@0
   459
	RPointerArray<TTransStatusPair> iTransStatArrayByTrans;
sl@0
   460
	RPointerArray<TTransStatusPair> iTransStatArrayByStatus;
sl@0
   461
	RPointerArray<TTransCbPair> iTransCbArrayByTrans;
sl@0
   462
	RPointerArray<TExtractInfo> iExtractInfoArray;
sl@0
   463
sl@0
   464
	// Support for Preamble testing
sl@0
   465
	TRequestStatus* iPreambleStatus;
sl@0
   466
	TRequestStatus* iMultiTranscStatus;
sl@0
   467
sl@0
   468
	// Support for buffer re-use testing
sl@0
   469
	TTransBufReuseData iTransBufReuseData;
sl@0
   470
sl@0
   471
	// Support for MasterSlave processing
sl@0
   472
	private:
sl@0
   473
	TInt InitSlaveClient();
sl@0
   474
sl@0
   475
	private:
sl@0
   476
	HBuf8* iConfigHdr;
sl@0
   477
	TRequestStatus* iStatus;
sl@0
   478
sl@0
   479
	public:
sl@0
   480
	void RequestComplete(TInt r);
sl@0
   481
sl@0
   482
	public:
sl@0
   483
	TIicBusSlaveCallback* iNotif;		// public to be accessible by callback
sl@0
   484
	TInt iChannelId;				// public to be accessible by callback
sl@0
   485
	TInt* iClientChanId;
sl@0
   486
sl@0
   487
#ifdef STANDALONE_CHANNEL
sl@0
   488
	//Used to store the captured channel
sl@0
   489
	struct TCapturedChannel
sl@0
   490
        {
sl@0
   491
        DIicClientChan* iChanPtr;
sl@0
   492
        TInt iChannelId;
sl@0
   493
        };
sl@0
   494
	TCapturedChannel iCapturedChannel;
sl@0
   495
#endif
sl@0
   496
	};
sl@0
   497
sl@0
   498
DDeviceIicClient::DDeviceIicClient()
sl@0
   499
// Constructor
sl@0
   500
    {
sl@0
   501
	CLIENT_PRINT(("> DDeviceIicClient::DDeviceIicClient()"));
sl@0
   502
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::DDeviceIicClient()"));
sl@0
   503
    iParseMask=0;		// No info, no PDD, no Units
sl@0
   504
    iUnitsMask=0;
sl@0
   505
    iVersion=TVersion(KIicClientMajorVersionNumber,
sl@0
   506
		      KIicClientMinorVersionNumber,
sl@0
   507
		      KIicClientBuildVersionNumber);
sl@0
   508
    }
sl@0
   509
#ifdef STANDALONE_CHANNEL
sl@0
   510
//  auxiliary function for ordering entries in the array of channels
sl@0
   511
TInt DChannelIicClient::OrderEntries(const DIicClientChan& aMatch, const DIicClientChan& aEntry)
sl@0
   512
	{
sl@0
   513
	TUint8 l=(TUint8)aMatch.GetChanNum();
sl@0
   514
	TUint8 r=(TUint8)aEntry.GetChanNum();
sl@0
   515
	if(l<r)
sl@0
   516
		return -1;
sl@0
   517
	else if(l>r)
sl@0
   518
		return 1;
sl@0
   519
	else
sl@0
   520
		return 0;
sl@0
   521
	}
sl@0
   522
// global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
sl@0
   523
TLinearOrder<DIicClientChan> EntryOrder(DChannelIicClient::OrderEntries);
sl@0
   524
sl@0
   525
// Store all the channels created by the client
sl@0
   526
RPointerArray<DIicClientChan> ChannelArray;
sl@0
   527
#endif /*STANDALONE_CHANNEL*/
sl@0
   528
sl@0
   529
DDeviceIicClient::~DDeviceIicClient()
sl@0
   530
    {
sl@0
   531
	CLIENT_PRINT(("> DDeviceIicClient::~DDeviceIicClient()"));
sl@0
   532
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::~DDeviceIicClient()"));
sl@0
   533
#ifdef STANDALONE_CHANNEL
sl@0
   534
    //For Standalone Channel, the client is responsible for channel destroy
sl@0
   535
    ChannelArray.ResetAndDestroy();
sl@0
   536
#endif
sl@0
   537
	}
sl@0
   538
sl@0
   539
TInt DDeviceIicClient::Install()
sl@0
   540
// Install the device driver.
sl@0
   541
    {
sl@0
   542
	CLIENT_PRINT(("> DDeviceIicClient::Install()"));
sl@0
   543
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceIicClient::Install()"));
sl@0
   544
    return(SetName(&KLddRootName));
sl@0
   545
    }
sl@0
   546
sl@0
   547
// Auxiliary functions for ordering entries in the array of TTransStatusPair pointers
sl@0
   548
// The first is to enable searching by Transaction (used by the callback)
sl@0
   549
// The second is to enable searching by the TRequestStatus (used by cancel calls)
sl@0
   550
TInt OrderEntriesByTrans(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
sl@0
   551
	{
sl@0
   552
	TUint l=(TUint)(aMatch.iTrans);
sl@0
   553
	TUint r=(TUint)(aEntry.iTrans);
sl@0
   554
	if(l>r)
sl@0
   555
		return -1;
sl@0
   556
	else if(l<r)
sl@0
   557
		return 1;
sl@0
   558
	else
sl@0
   559
		return 0;
sl@0
   560
	}
sl@0
   561
TLinearOrder<TTransStatusPair> TransStatusOrderByTrans(OrderEntriesByTrans);
sl@0
   562
sl@0
   563
TInt OrderEntriesByStatus(const TTransStatusPair& aMatch, const TTransStatusPair& aEntry)
sl@0
   564
	{
sl@0
   565
	TUint l=(TUint)(aMatch.iReq);
sl@0
   566
	TUint r=(TUint)(aEntry.iReq);
sl@0
   567
	if(l>r)
sl@0
   568
		return -1;
sl@0
   569
	else if(l<r)
sl@0
   570
		return 1;
sl@0
   571
	else
sl@0
   572
		return 0;
sl@0
   573
	}
sl@0
   574
TLinearOrder<TTransStatusPair> TransStatusOrderByStatus(OrderEntriesByStatus);
sl@0
   575
sl@0
   576
// Auxilliary function to track callback objects assigned to asynchronous transactions
sl@0
   577
TInt OrderCbEntriesByTrans(const TTransCbPair& aMatch, const TTransCbPair& aEntry)
sl@0
   578
	{
sl@0
   579
	TUint l=(TUint)(aMatch.iTrans);
sl@0
   580
	TUint r=(TUint)(aEntry.iTrans);
sl@0
   581
	if(l>r)
sl@0
   582
		return -1;
sl@0
   583
	else if(l<r)
sl@0
   584
		return 1;
sl@0
   585
	else
sl@0
   586
		return 0;
sl@0
   587
	}
sl@0
   588
TLinearOrder<TTransCbPair> TransCbOrderByTrans(OrderCbEntriesByTrans);
sl@0
   589
sl@0
   590
TInt OrderExtractInfoByTrans(const TExtractInfo& aMatch, const TExtractInfo& aEntry)
sl@0
   591
    {
sl@0
   592
    TUint l=(TUint)(aMatch.iTrans);
sl@0
   593
    TUint r=(TUint)(aEntry.iTrans);
sl@0
   594
    if(l>r)
sl@0
   595
        return -1;
sl@0
   596
    else if(l<r)
sl@0
   597
        return 1;
sl@0
   598
    else
sl@0
   599
        return 0;
sl@0
   600
    }
sl@0
   601
TLinearOrder<TExtractInfo> ExtractInfoOrderByTrans(OrderExtractInfoByTrans);
sl@0
   602
sl@0
   603
sl@0
   604
_LIT(KLitArrayMutexName,"IIC_CLIENT_ARRAY_MUTEX");
sl@0
   605
_LIT(KLitArraySemName,"IIC_CLIENT_ARRAY_SEM");
sl@0
   606
#define IIC_CLIENT_MUTEX_ORDER KMutexOrdGeneral4	// Semi-arbitrary - middle of general purpose range, allow higher and lower priorities
sl@0
   607
sl@0
   608
TInt DChannelIicClient::InitIicClient()
sl@0
   609
	{
sl@0
   610
	TInt r = Kern::MutexCreate(iArrayMutex,KLitArrayMutexName,IIC_CLIENT_MUTEX_ORDER);
sl@0
   611
	if(r!=KErrNone)
sl@0
   612
		return r;
sl@0
   613
	r = Kern::SemaphoreCreate(iChanArrWrtSem,KLitArraySemName,1); // Initial count of one allows first wait to be non-blocking
sl@0
   614
	if(r!=KErrNone)
sl@0
   615
		iArrayMutex->Close(NULL);
sl@0
   616
sl@0
   617
	return r;
sl@0
   618
	}
sl@0
   619
sl@0
   620
TInt DChannelIicClient::InsertPairs(TTransStatusPair* aPair, TTransCbPair* aCbPair)
sl@0
   621
	{
sl@0
   622
	CLIENT_PRINT(("DChannelIicClient::InsertPairs invoked with aPair=0x%x, aPair->iReq=0x%x, aPair-iTrans=0x%x\n",aPair,aPair->iReq,aPair->iTrans ));
sl@0
   623
	CLIENT_PRINT(("DChannelIicClient::InsertPairs ... and aCbPair=0x%x, aCbPair->iCb=0x%x, aCbPair-iTrans=0x%x\n",aCbPair,aCbPair->iCb,aCbPair->iTrans ));
sl@0
   624
	TInt r = KErrNone;
sl@0
   625
sl@0
   626
	GetWriteAccess();
sl@0
   627
	Lock();
sl@0
   628
sl@0
   629
	if((r = iTransStatArrayByTrans.InsertInOrder(aPair,TransStatusOrderByTrans)) == KErrNone)
sl@0
   630
		{
sl@0
   631
		if((r = iTransStatArrayByStatus.InsertInOrder(aPair,TransStatusOrderByStatus)) == KErrNone)
sl@0
   632
			{
sl@0
   633
			if((r = iTransCbArrayByTrans.InsertInOrder(aCbPair,TransCbOrderByTrans))!=KErrNone)
sl@0
   634
				{
sl@0
   635
				CLIENT_PRINT(("DChannelIicClient::InsertPairs, aCbPair=0x%x InsertInOrder(status) returned %d\n",aCbPair,r));
sl@0
   636
				}
sl@0
   637
			}
sl@0
   638
		else
sl@0
   639
			{
sl@0
   640
			CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(status) returned %d\n",aPair,r));
sl@0
   641
			}
sl@0
   642
		}
sl@0
   643
	else
sl@0
   644
		{
sl@0
   645
		CLIENT_PRINT(("DChannelIicClient::InsertPairs, aPair=0x%x InsertInOrder(trans) returned %d\n",aPair,r));
sl@0
   646
		}
sl@0
   647
	FreeWriteAccess();
sl@0
   648
	Unlock();
sl@0
   649
	return r;
sl@0
   650
	}
sl@0
   651
sl@0
   652
//dummy call back func is provided for asyn call in priority test
sl@0
   653
static void DummyCallbackFunc(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt /*aResult*/, TAny* /*aParam*/)
sl@0
   654
	{
sl@0
   655
	//do nothing
sl@0
   656
	}
sl@0
   657
sl@0
   658
static void AsyncCallbackFunc(TIicBusTransaction* aTrans, TInt aBusId, TInt aResult, TAny* aParam)
sl@0
   659
	{
sl@0
   660
	(void)aBusId; // aBusId is not used if CLIENT_PRINT is disabled
sl@0
   661
	CLIENT_PRINT(("> AsyncCallbackFunc() - aTrans=0x%x, aBusId=0x%x, aResult=%d, aParam=0x%x\n",aTrans,aBusId,aResult,aParam));
sl@0
   662
	DChannelIicClient* channel = (DChannelIicClient*)aParam;
sl@0
   663
	CLIENT_PRINT(("AsyncCallbackFunc() - channel=0x%x\n",channel));
sl@0
   664
sl@0
   665
	// Use the channel to get the user-side client's TRequestStatus and complete it with aResult
sl@0
   666
	TTransStatusPair* searchPair = new TTransStatusPair();
sl@0
   667
	searchPair->iTrans = aTrans;
sl@0
   668
	channel->GetWriteAccess();
sl@0
   669
	channel->Lock();
sl@0
   670
	TInt pairIndex = (channel->iTransStatArrayByTrans).FindInOrder(searchPair,TransStatusOrderByTrans);
sl@0
   671
	delete searchPair;
sl@0
   672
	if(pairIndex<0)
sl@0
   673
		{
sl@0
   674
		CLIENT_PRINT(("AsyncCallbackFunc() - (trans) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
sl@0
   675
		return;
sl@0
   676
		}
sl@0
   677
	TTransStatusPair* pairPtr = (channel->iTransStatArrayByTrans)[pairIndex];
sl@0
   678
	TRequestStatus* status = pairPtr->iReq;
sl@0
   679
sl@0
   680
	// Now remove the TTransStatusPair objects in iTransStatArrayByTrans, iTransStatArrayByStatus
sl@0
   681
	(channel->iTransStatArrayByTrans).Remove(pairIndex);
sl@0
   682
	pairIndex = (channel->iTransStatArrayByStatus).FindInOrder(pairPtr,TransStatusOrderByStatus);
sl@0
   683
	if(pairIndex<0)
sl@0
   684
		{
sl@0
   685
		CLIENT_PRINT(("AsyncCallbackFunc() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndex,status));
sl@0
   686
		return;
sl@0
   687
		}
sl@0
   688
	(channel->iTransStatArrayByStatus).Remove(pairIndex);
sl@0
   689
sl@0
   690
	// Now remove the TTransCbPair object in iTransCbArrayByTrans
sl@0
   691
	TTransCbPair* SearchCbPair = new TTransCbPair();
sl@0
   692
	SearchCbPair->iTrans = aTrans;
sl@0
   693
	pairIndex = (channel->iTransCbArrayByTrans).FindInOrder(SearchCbPair,TransCbOrderByTrans);
sl@0
   694
	delete SearchCbPair;
sl@0
   695
	if(pairIndex<0)
sl@0
   696
		{
sl@0
   697
		CLIENT_PRINT(("AsyncCallbackFunc() - (cb) FindInOrder returned %d (aTrans=0x%x)\n",pairIndex,aTrans));
sl@0
   698
		return;
sl@0
   699
		}
sl@0
   700
	TTransCbPair* cbPair = (channel->iTransCbArrayByTrans)[pairIndex];
sl@0
   701
	(channel->iTransCbArrayByTrans).Remove(pairIndex);
sl@0
   702
	delete cbPair->iCb;
sl@0
   703
	delete cbPair;
sl@0
   704
	channel->FreeWriteAccess();
sl@0
   705
	channel->Unlock();
sl@0
   706
	Kern::RequestComplete(channel->iClient, status, aResult);
sl@0
   707
	// We should call CleanupExtractTrans() to delete all the objects created in ExtractTransData()
sl@0
   708
	channel->CleanupExtractTrans(pairPtr->iTrans);
sl@0
   709
	// The object referred to be pairPtr is finished with and can be deleted
sl@0
   710
	channel->CleanupTransaction(pairPtr->iTrans);
sl@0
   711
	delete pairPtr;
sl@0
   712
	}
sl@0
   713
sl@0
   714
sl@0
   715
void DDeviceIicClient::GetCaps(TDes8& aDes) const
sl@0
   716
// Return the IicClient capabilities.
sl@0
   717
    {
sl@0
   718
	CLIENT_PRINT(("> DDeviceIicClient::GetCaps(TDes8& aDes) const"));
sl@0
   719
    TPckgBuf<TCapsIicClient> b;
sl@0
   720
    b().version=TVersion(KIicClientMajorVersionNumber,
sl@0
   721
			 KIicClientMinorVersionNumber,
sl@0
   722
			 KIicClientBuildVersionNumber);
sl@0
   723
    Kern::InfoCopy(aDes,b);
sl@0
   724
    }
sl@0
   725
sl@0
   726
sl@0
   727
TInt DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)
sl@0
   728
// Create a channel on the device.
sl@0
   729
    {
sl@0
   730
	CLIENT_PRINT(("> DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)"));
sl@0
   731
	if(iOpenChannels>=KMaxNumChannels)
sl@0
   732
		return KErrOverflow;
sl@0
   733
    aChannel=new DChannelIicClient;
sl@0
   734
    return aChannel?KErrNone:KErrNoMemory;
sl@0
   735
    }
sl@0
   736
sl@0
   737
#ifdef STANDALONE_CHANNEL
sl@0
   738
sl@0
   739
TInt GetChanPtr(const TInt aBusId, TInt &aIndex, DIicClientChan*& aChan)
sl@0
   740
	{
sl@0
   741
    __KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, aBusId=0x%x\n",aBusId));
sl@0
   742
	TInt32 chanId;
sl@0
   743
	chanId = GET_CHAN_NUM(aBusId);
sl@0
   744
	__KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, chanId=0x%x\n",chanId));
sl@0
   745
	DIicClientChan chanEntry(NULL,(TInt8)chanId, DIicBusChannel::EMasterSlave);
sl@0
   746
	TInt r = KErrNotFound;
sl@0
   747
	aIndex = ChannelArray.FindInOrder(&chanEntry, EntryOrder);
sl@0
   748
	if(aIndex >= 0)
sl@0
   749
		{
sl@0
   750
		aChan = ChannelArray[aIndex];
sl@0
   751
		r = KErrNone;
sl@0
   752
		}
sl@0
   753
sl@0
   754
	__KTRACE_OPT(KIIC, 	Kern::Printf("GetChanPtr, chanPtr=0x%x, index=%d\n",aChan,aIndex));
sl@0
   755
	return r;
sl@0
   756
	}
sl@0
   757
#endif
sl@0
   758
sl@0
   759
DECLARE_STANDARD_LDD()
sl@0
   760
	{
sl@0
   761
	//If in STANDALONE_CHANNEL mode, the client creates a list of channels
sl@0
   762
#ifdef STANDALONE_CHANNEL
sl@0
   763
	DIicClientChan* aClientChan;
sl@0
   764
	TInt r = KErrNone;
sl@0
   765
	DIicBusChannel *chan = NULL, *chanM = NULL, *chanS = NULL;
sl@0
   766
	TInt i;
sl@0
   767
	for(i=0; i<NUM_CHANNELS_SPI; i++)
sl@0
   768
		{
sl@0
   769
		CLIENT_PRINT(("\n"));
sl@0
   770
#if defined(MASTER_MODE)
sl@0
   771
		if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::EMaster))
sl@0
   772
			{
sl@0
   773
			chan=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
sl@0
   774
			if(!chan)
sl@0
   775
			    {
sl@0
   776
			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
sl@0
   777
				return NULL;
sl@0
   778
			    }
sl@0
   779
			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
sl@0
   780
			if(((DSimulatedIicBusChannelMasterSpi*)chan)->Create()!=KErrNone)
sl@0
   781
			    {
sl@0
   782
			    delete chan;
sl@0
   783
				return NULL;
sl@0
   784
			    }
sl@0
   785
			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMaster);
sl@0
   786
            if(!aClientChan)
sl@0
   787
                {
sl@0
   788
                delete chan;
sl@0
   789
                return NULL;
sl@0
   790
                }
sl@0
   791
            r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   792
            if(r!=KErrNone)
sl@0
   793
                {
sl@0
   794
                delete chan;
sl@0
   795
                delete aClientChan;
sl@0
   796
                break;
sl@0
   797
                }
sl@0
   798
			}
sl@0
   799
#endif
sl@0
   800
#if defined(MASTER_MODE) && defined(SLAVE_MODE)
sl@0
   801
		if(CHANNEL_TYPE_SPI(i) == DIicBusChannel::EMasterSlave)
sl@0
   802
			{
sl@0
   803
			//For MasterSlave channel, the client creates a Master channel, a Slave
sl@0
   804
			//channel and a MasterSlave Channel, then store all of them in ChannelArray.
sl@0
   805
			chanM=new DSimulatedIicBusChannelMasterSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
sl@0
   806
			if(!chanM)
sl@0
   807
				return NULL;
sl@0
   808
sl@0
   809
			chanS=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
sl@0
   810
			if(!chanS)
sl@0
   811
			    {
sl@0
   812
			    delete chanM;
sl@0
   813
				return NULL;
sl@0
   814
			    }
sl@0
   815
			chan=new DIicBusChannelMasterSlave(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i),(DSimulatedIicBusChannelMasterSpi*)chanM,(DSimulatedIicBusChannelSlaveSpi*)chanS); // Generic implementation
sl@0
   816
			if(!chan)
sl@0
   817
			    {
sl@0
   818
			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
sl@0
   819
			    delete chanM;
sl@0
   820
			    delete chanS;
sl@0
   821
				return NULL;
sl@0
   822
			    }
sl@0
   823
			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
sl@0
   824
			if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
sl@0
   825
			    {
sl@0
   826
			    delete chanM;
sl@0
   827
			    delete chanS;
sl@0
   828
			    delete chan;
sl@0
   829
				return NULL;
sl@0
   830
			    }
sl@0
   831
			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::EMasterSlave);
sl@0
   832
			if(!aClientChan)
sl@0
   833
			    {
sl@0
   834
			    delete chanM;
sl@0
   835
			    delete chanS;
sl@0
   836
			    delete chan;
sl@0
   837
			    return NULL;
sl@0
   838
			    }
sl@0
   839
            r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   840
            if(r!=KErrNone)
sl@0
   841
                {
sl@0
   842
                delete chanM;
sl@0
   843
                delete chanS;
sl@0
   844
                delete chan;
sl@0
   845
                delete aClientChan;
sl@0
   846
                break;
sl@0
   847
                }
sl@0
   848
			}
sl@0
   849
#endif
sl@0
   850
#if defined(SLAVE_MODE)
sl@0
   851
		if(CHANNEL_TYPE_SPI(i) == (DIicBusChannel::ESlave))
sl@0
   852
			{
sl@0
   853
			chan=new DSimulatedIicBusChannelSlaveSpi(BUS_TYPE_SPI,CHANNEL_DUPLEX_SPI(i));
sl@0
   854
			if(!chan)
sl@0
   855
			    {
sl@0
   856
			    CLIENT_PRINT(("\n\nSpi: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_SPI(i),i));
sl@0
   857
				return NULL;
sl@0
   858
			    }
sl@0
   859
			CLIENT_PRINT(("SPI chan created at 0x%x\n",chan));
sl@0
   860
			if(((DSimulatedIicBusChannelSlaveSpi*)chan)->Create()!=KErrNone)
sl@0
   861
			    {
sl@0
   862
			    delete chan;
sl@0
   863
				return NULL;
sl@0
   864
			    }
sl@0
   865
			aClientChan = new DIicClientChan(chan,AssignChanNumSpi(),DIicBusChannel::ESlave);
sl@0
   866
            if(!aClientChan)
sl@0
   867
                {
sl@0
   868
                delete chan;
sl@0
   869
                return NULL;
sl@0
   870
                }
sl@0
   871
            r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   872
            if(r!=KErrNone)
sl@0
   873
                {
sl@0
   874
                delete chan;
sl@0
   875
                delete aClientChan;
sl@0
   876
                break;
sl@0
   877
                }
sl@0
   878
			}
sl@0
   879
#endif
sl@0
   880
#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
sl@0
   881
#error I2C mode not defined as Master, Slave nor Master-Slave
sl@0
   882
#endif
sl@0
   883
		}
sl@0
   884
sl@0
   885
	for(i=0; i<NUM_CHANNELS_I2C; i++)
sl@0
   886
			{
sl@0
   887
			CLIENT_PRINT(("\n"));
sl@0
   888
	#if defined(MASTER_MODE)
sl@0
   889
			if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::EMaster))
sl@0
   890
				{
sl@0
   891
				chan=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
sl@0
   892
				if(!chan)
sl@0
   893
				    {
sl@0
   894
				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
sl@0
   895
					return NULL;
sl@0
   896
				    }
sl@0
   897
				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
sl@0
   898
				if(((DSimulatedIicBusChannelMasterI2c*)chan)->Create()!=KErrNone)
sl@0
   899
				    {
sl@0
   900
				    delete chan;
sl@0
   901
					return NULL;
sl@0
   902
					}
sl@0
   903
				aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMaster);
sl@0
   904
				if(!aClientChan)
sl@0
   905
				    {
sl@0
   906
				    delete chan;
sl@0
   907
				    return NULL;
sl@0
   908
				    }
sl@0
   909
                r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   910
                if(r!=KErrNone)
sl@0
   911
                    {
sl@0
   912
                    delete chan;
sl@0
   913
                    delete aClientChan;
sl@0
   914
                    break;
sl@0
   915
                    }
sl@0
   916
				}
sl@0
   917
	#endif
sl@0
   918
	#if defined(MASTER_MODE) && defined(SLAVE_MODE)
sl@0
   919
			if(CHANNEL_TYPE_I2C(i) == DIicBusChannel::EMasterSlave)
sl@0
   920
				{
sl@0
   921
				chanM=new DSimulatedIicBusChannelMasterI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
sl@0
   922
				if(!chanM)
sl@0
   923
					return NULL;
sl@0
   924
sl@0
   925
				chanS=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
sl@0
   926
				if(!chanS)
sl@0
   927
				    {
sl@0
   928
				    delete chanM;
sl@0
   929
					return NULL;
sl@0
   930
				    }
sl@0
   931
				//The client doesn't create the Master and Slave channels, as they should be created
sl@0
   932
				//in MasterSlave channel's DoCreate().
sl@0
   933
				chan=new DSimulatedIicBusChannelMasterSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i),(DSimulatedIicBusChannelMasterI2c*)chanM,(DSimulatedIicBusChannelSlaveI2c*)chanS); // Generic implementation
sl@0
   934
				if(!chan)
sl@0
   935
				    {
sl@0
   936
				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
sl@0
   937
				    delete chanM;
sl@0
   938
				    delete chanS;
sl@0
   939
					return NULL;
sl@0
   940
				    }
sl@0
   941
				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
sl@0
   942
				if(((DIicBusChannelMasterSlave*)chan)->DoCreate()!=KErrNone)
sl@0
   943
				    {
sl@0
   944
				    delete chanM;
sl@0
   945
				    delete chanS;
sl@0
   946
				    delete chan;
sl@0
   947
					return NULL;
sl@0
   948
				    }
sl@0
   949
			    aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::EMasterSlave);
sl@0
   950
                if(!aClientChan)
sl@0
   951
                    {
sl@0
   952
                    delete chanM;
sl@0
   953
                    delete chanS;
sl@0
   954
                    delete chan;
sl@0
   955
                    return NULL;
sl@0
   956
                    }
sl@0
   957
                r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   958
                if(r!=KErrNone)
sl@0
   959
                    {
sl@0
   960
                    delete chanM;
sl@0
   961
                    delete chanS;
sl@0
   962
                    delete chan;
sl@0
   963
                    delete aClientChan;
sl@0
   964
                    break;
sl@0
   965
                    }
sl@0
   966
				}
sl@0
   967
	#endif
sl@0
   968
	#if defined(SLAVE_MODE)
sl@0
   969
			if(CHANNEL_TYPE_I2C(i) == (DIicBusChannel::ESlave))
sl@0
   970
				{
sl@0
   971
				chan=new DSimulatedIicBusChannelSlaveI2c(BUS_TYPE_I2C,CHANNEL_DUPLEX_I2C(i));
sl@0
   972
				if(!chan)
sl@0
   973
				    {
sl@0
   974
				    CLIENT_PRINT(("\n\nI2C: Channel of type (%d) not created for index %d\n\n",CHANNEL_TYPE_I2C(i),i));
sl@0
   975
					return NULL;
sl@0
   976
				    }
sl@0
   977
				CLIENT_PRINT(("I2C chan created at 0x%x\n",chan));
sl@0
   978
				if(((DSimulatedIicBusChannelSlaveI2c*)chan)->Create()!=KErrNone)
sl@0
   979
				    {
sl@0
   980
				    delete chan;
sl@0
   981
					return NULL;
sl@0
   982
				    }
sl@0
   983
			    aClientChan = new DIicClientChan(chan,AssignChanNumI2c(),DIicBusChannel::ESlave);
sl@0
   984
                if(!aClientChan)
sl@0
   985
                    {
sl@0
   986
                    delete chan;
sl@0
   987
                    return NULL;
sl@0
   988
                    }
sl@0
   989
                r = ChannelArray.InsertInOrder(aClientChan,EntryOrder);
sl@0
   990
                if(r!=KErrNone)
sl@0
   991
                    {
sl@0
   992
                    delete chan;
sl@0
   993
                    delete aClientChan;
sl@0
   994
                    break;
sl@0
   995
                    }
sl@0
   996
				}
sl@0
   997
	#endif
sl@0
   998
	#if !defined(MASTER_MODE) && !defined(SLAVE_MODE)
sl@0
   999
	#error I2C mode not defined as Master, Slave nor Master-Slave
sl@0
  1000
	#endif
sl@0
  1001
			}
sl@0
  1002
sl@0
  1003
#endif
sl@0
  1004
	return new DDeviceIicClient;
sl@0
  1005
	}
sl@0
  1006
sl@0
  1007
sl@0
  1008
sl@0
  1009
DChannelIicClient::DChannelIicClient()
sl@0
  1010
// Constructor
sl@0
  1011
    {
sl@0
  1012
	CLIENT_PRINT(("> DChannelIicClient::DChannelIicClient()"));
sl@0
  1013
    iClient=&Kern::CurrentThread();
sl@0
  1014
	// Increase the DThread's ref count so that it does not close without us
sl@0
  1015
	iClient->Open();
sl@0
  1016
    }
sl@0
  1017
sl@0
  1018
DChannelIicClient::~DChannelIicClient()
sl@0
  1019
// Destructor
sl@0
  1020
    {
sl@0
  1021
	CLIENT_PRINT(("> DChannelIicClient::~DChannelIicClient()"));
sl@0
  1022
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelIicClient::~DChannelIicClient()"));
sl@0
  1023
    delete iNotif;
sl@0
  1024
    iArrayMutex->Close(NULL);
sl@0
  1025
    iChanArrWrtSem->Close(NULL);
sl@0
  1026
	iDfcQue->Destroy();
sl@0
  1027
	// decrement the DThread's reference count
sl@0
  1028
	Kern::SafeClose((DObject*&)iClient, NULL);
sl@0
  1029
sl@0
  1030
    iTransStatArrayByTrans.Reset();
sl@0
  1031
    iTransStatArrayByStatus.Reset();
sl@0
  1032
    iTransCbArrayByTrans.Reset();
sl@0
  1033
	iExtractInfoArray.Reset();
sl@0
  1034
	}
sl@0
  1035
sl@0
  1036
sl@0
  1037
TInt DChannelIicClient::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
sl@0
  1038
	{
sl@0
  1039
	CLIENT_PRINT(("> DChannelIicClient::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
sl@0
  1040
	TInt r = Kern::DynamicDfcQCreate(iDfcQue,KIicClientThreadPriority,KIicClientThreadName);
sl@0
  1041
	if(r!=KErrNone)
sl@0
  1042
		return r;
sl@0
  1043
	SetDfcQ(iDfcQue);
sl@0
  1044
	iMsgQ.Receive();
sl@0
  1045
sl@0
  1046
	r = InitIicClient();
sl@0
  1047
	return r;
sl@0
  1048
	}
sl@0
  1049
sl@0
  1050
void DChannelIicClient::HandleMsg(TMessageBase* aMsg)
sl@0
  1051
	{
sl@0
  1052
	TThreadMessage& m=*(TThreadMessage*)aMsg;
sl@0
  1053
    TInt id=m.iValue;
sl@0
  1054
sl@0
  1055
	CLIENT_PRINT((" >ldd: DChannelIicClient::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
sl@0
  1056
sl@0
  1057
	if (id == (TInt)ECloseMsg)
sl@0
  1058
		{
sl@0
  1059
	    iMsgQ.iMessage->Complete(KErrNone,EFalse);
sl@0
  1060
		return;
sl@0
  1061
		}
sl@0
  1062
    else if (id == KMaxTInt)
sl@0
  1063
		{
sl@0
  1064
		DoCancel(m.Int0());
sl@0
  1065
		m.Complete(KErrNone,ETrue);
sl@0
  1066
		return;
sl@0
  1067
		}
sl@0
  1068
sl@0
  1069
    if (id<0)
sl@0
  1070
		{
sl@0
  1071
		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
sl@0
  1072
		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
sl@0
  1073
		if (r!=KErrNone)
sl@0
  1074
			{
sl@0
  1075
	    	Kern::RequestComplete(iClient, pS, r);
sl@0
  1076
			}
sl@0
  1077
		m.Complete(KErrNone,ETrue);
sl@0
  1078
		}
sl@0
  1079
    else
sl@0
  1080
		{
sl@0
  1081
		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
sl@0
  1082
		m.Complete(r,ETrue);
sl@0
  1083
		}
sl@0
  1084
	}
sl@0
  1085
sl@0
  1086
TInt DChannelIicClient::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback/*NULL*/)
sl@0
  1087
	{
sl@0
  1088
	TInt r = KErrNone;
sl@0
  1089
#ifndef STANDALONE_CHANNEL
sl@0
  1090
	if(!aCallback)
sl@0
  1091
		r = IicBus::QueueTransaction(aBusId, aTransaction);
sl@0
  1092
	else
sl@0
  1093
		r = IicBus::QueueTransaction(aBusId, aTransaction, aCallback);
sl@0
  1094
#else
sl@0
  1095
	__KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
sl@0
  1096
	if(!aTransaction)
sl@0
  1097
		{
sl@0
  1098
		return KErrArgument;
sl@0
  1099
		}
sl@0
  1100
sl@0
  1101
	// Get a pointer to the channel
sl@0
  1102
	TInt dumInt = 0;
sl@0
  1103
	DIicClientChan* chanPtr = NULL;
sl@0
  1104
	r = GetChanPtr(aBusId, dumInt, chanPtr);
sl@0
  1105
	if(r == KErrNone)
sl@0
  1106
		{
sl@0
  1107
		if(!chanPtr)
sl@0
  1108
			{
sl@0
  1109
			r = KErrArgument;
sl@0
  1110
			}
sl@0
  1111
		else
sl@0
  1112
			{
sl@0
  1113
			switch(chanPtr->GetChanType())
sl@0
  1114
				{
sl@0
  1115
				// QueueTransaction requests are only supported by channels in Master mode.
sl@0
  1116
				case DIicBusChannel::ESlave:
sl@0
  1117
					{
sl@0
  1118
					r = KErrNotSupported;
sl@0
  1119
					break;
sl@0
  1120
					}
sl@0
  1121
				// If the request is supported by the Master channel, send it to the channel for processing in its thread
sl@0
  1122
				case DIicBusChannel::EMasterSlave:
sl@0
  1123
					{
sl@0
  1124
sl@0
  1125
					aTransaction->iBusId = aBusId;
sl@0
  1126
					if(!aCallback)
sl@0
  1127
					    r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));					    
sl@0
  1128
					else
sl@0
  1129
						r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
sl@0
  1130
					break;
sl@0
  1131
					}
sl@0
  1132
				case DIicBusChannel::EMaster:
sl@0
  1133
					{
sl@0
  1134
					aTransaction->iBusId = aBusId;
sl@0
  1135
					if(!aCallback)
sl@0
  1136
						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction));
sl@0
  1137
					else
sl@0
  1138
						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->QueueTransaction(aTransaction, aCallback));
sl@0
  1139
					break;
sl@0
  1140
					}
sl@0
  1141
				default:
sl@0
  1142
					{
sl@0
  1143
					r = KErrGeneral;
sl@0
  1144
					}
sl@0
  1145
				}
sl@0
  1146
			}
sl@0
  1147
		}
sl@0
  1148
#endif
sl@0
  1149
	return r;
sl@0
  1150
	}
sl@0
  1151
sl@0
  1152
TInt DChannelIicClient::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
sl@0
  1153
	{
sl@0
  1154
	TInt r = KErrNone;
sl@0
  1155
#ifndef STANDALONE_CHANNEL
sl@0
  1156
	r = IicBus::CancelTransaction(aBusId, aTransaction);
sl@0
  1157
#else
sl@0
  1158
    __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
sl@0
  1159
	if(!aTransaction)
sl@0
  1160
		{
sl@0
  1161
		return KErrArgument;
sl@0
  1162
		}
sl@0
  1163
sl@0
  1164
	// Get the channel
sl@0
  1165
	TInt dumInt = 0;
sl@0
  1166
	DIicClientChan* chanPtr = NULL;
sl@0
  1167
	if(r == KErrNone)
sl@0
  1168
		{
sl@0
  1169
		r = GetChanPtr(aBusId, dumInt, chanPtr);
sl@0
  1170
		if(r == KErrNone)
sl@0
  1171
			{
sl@0
  1172
			if(!chanPtr)
sl@0
  1173
				{
sl@0
  1174
				r = KErrArgument;
sl@0
  1175
				}
sl@0
  1176
			else
sl@0
  1177
				{
sl@0
  1178
				// QueueTransaction requests are only supported by channels in Master mode.
sl@0
  1179
				switch(chanPtr->GetChanType())
sl@0
  1180
					{
sl@0
  1181
					case DIicBusChannel::ESlave:
sl@0
  1182
						{
sl@0
  1183
						r = KErrNotSupported;
sl@0
  1184
						break;
sl@0
  1185
						}
sl@0
  1186
					case DIicBusChannel::EMasterSlave:
sl@0
  1187
						{
sl@0
  1188
						r = (((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
sl@0
  1189
						break;
sl@0
  1190
						}
sl@0
  1191
					case DIicBusChannel::EMaster:
sl@0
  1192
						{
sl@0
  1193
						r = (((DIicBusChannelMaster*) (chanPtr->GetChannelPtr()))->CancelTransaction(aTransaction));
sl@0
  1194
						break;
sl@0
  1195
						}
sl@0
  1196
					default:
sl@0
  1197
						{
sl@0
  1198
						r = KErrGeneral;
sl@0
  1199
						}
sl@0
  1200
					}
sl@0
  1201
				}
sl@0
  1202
			}
sl@0
  1203
		}
sl@0
  1204
#endif
sl@0
  1205
	return r;
sl@0
  1206
	}
sl@0
  1207
sl@0
  1208
sl@0
  1209
TInt DChannelIicClient::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
sl@0
  1210
	{
sl@0
  1211
	TInt r = KErrNone;
sl@0
  1212
#ifndef STANDALONE_CHANNEL
sl@0
  1213
	r = IicBus::StaticExtension(aId, aFunction, aParam1, aParam2);
sl@0
  1214
#else
sl@0
  1215
	// Get the channel
sl@0
  1216
	TInt dumInt = 0;
sl@0
  1217
	DIicClientChan* chanPtr = NULL;
sl@0
  1218
	if(r == KErrNone)
sl@0
  1219
		{
sl@0
  1220
		r = GetChanPtr(aId, dumInt, chanPtr);
sl@0
  1221
		if(r == KErrNone)
sl@0
  1222
			{
sl@0
  1223
			if(!chanPtr)
sl@0
  1224
				{
sl@0
  1225
				r = KErrArgument;
sl@0
  1226
				}
sl@0
  1227
			else
sl@0
  1228
				{
sl@0
  1229
				r = (chanPtr->GetChannelPtr())->StaticExtension(aFunction, aParam1, aParam2);
sl@0
  1230
				}
sl@0
  1231
			}
sl@0
  1232
		}
sl@0
  1233
#endif
sl@0
  1234
	return r;
sl@0
  1235
	}
sl@0
  1236
sl@0
  1237
TInt DChannelIicClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
sl@0
  1238
	{
sl@0
  1239
	TInt r = KErrNone;
sl@0
  1240
#ifndef STANDALONE_CHANNEL
sl@0
  1241
	r = IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
sl@0
  1242
#else
sl@0
  1243
	// Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
sl@0
  1244
	if(!aCallback || !aConfigHdr)
sl@0
  1245
		{
sl@0
  1246
		return KErrArgument;
sl@0
  1247
		}
sl@0
  1248
sl@0
  1249
	// Get the channel
sl@0
  1250
	TInt chanIndex = 0;
sl@0
  1251
	DIicClientChan* chanPtr = NULL;
sl@0
  1252
	if(r == KErrNone)
sl@0
  1253
		{
sl@0
  1254
		r = GetChanPtr(aBusId, chanIndex, chanPtr);
sl@0
  1255
		if(r == KErrNone)
sl@0
  1256
			{
sl@0
  1257
			if(!chanPtr)
sl@0
  1258
				{
sl@0
  1259
				r = KErrArgument;
sl@0
  1260
				}
sl@0
  1261
			else
sl@0
  1262
				{
sl@0
  1263
				switch(chanPtr->GetChanType())
sl@0
  1264
					{
sl@0
  1265
					// CaptureChannel requests are only supported by channels in Slave mode.
sl@0
  1266
					case DIicBusChannel::EMaster:
sl@0
  1267
						{
sl@0
  1268
						r = KErrNotSupported;
sl@0
  1269
						break;
sl@0
  1270
						}
sl@0
  1271
					case DIicBusChannel::EMasterSlave:
sl@0
  1272
						{
sl@0
  1273
						r = ((DIicBusChannelMasterSlave*) (chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
sl@0
  1274
						break;
sl@0
  1275
						}
sl@0
  1276
					case DIicBusChannel::ESlave:
sl@0
  1277
						{
sl@0
  1278
						r = ((DIicBusChannelSlave*)(chanPtr->GetChannelPtr()))->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
sl@0
  1279
						break;
sl@0
  1280
						}
sl@0
  1281
					default:
sl@0
  1282
						{
sl@0
  1283
						r = KErrArgument;
sl@0
  1284
						}
sl@0
  1285
					}
sl@0
  1286
				// For synchronous capture, if successful then install the channel
sl@0
  1287
				if(r == KErrNone)
sl@0
  1288
					{
sl@0
  1289
					if(!aAsynch)
sl@0
  1290
						{
sl@0
  1291
						 iCapturedChannel.iChanPtr = chanPtr;
sl@0
  1292
						 iCapturedChannel.iChannelId = iChannelId;
sl@0
  1293
						}
sl@0
  1294
					else
sl@0
  1295
						//For asynchronous capture, record chanPtr, if later failed capture,
sl@0
  1296
						//clean iCapturedChannel in client's callback.
sl@0
  1297
						iCapturedChannel.iChanPtr = chanPtr;
sl@0
  1298
					}
sl@0
  1299
				}
sl@0
  1300
			}
sl@0
  1301
		}
sl@0
  1302
#endif
sl@0
  1303
	return r;
sl@0
  1304
	}
sl@0
  1305
sl@0
  1306
TInt DChannelIicClient::ReleaseChannel(TInt aChannelId)
sl@0
  1307
	{
sl@0
  1308
	TInt r = KErrNone;
sl@0
  1309
#ifndef STANDALONE_CHANNEL
sl@0
  1310
	r = IicBus::ReleaseChannel(aChannelId);
sl@0
  1311
#else
sl@0
  1312
    __KTRACE_OPT(KIIC, Kern::Printf("DChannelIicClient::ReleaseChannel, channelID = 0x%x \n",aChannelId));
sl@0
  1313
    if(iCapturedChannel.iChannelId != aChannelId)
sl@0
  1314
            return KErrNotFound;
sl@0
  1315
sl@0
  1316
    if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::EMasterSlave)
sl@0
  1317
        r = ((DIicBusChannelMasterSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
sl@0
  1318
    else if((iCapturedChannel.iChanPtr)->GetChanType() == DIicBusChannel::ESlave)
sl@0
  1319
        r = ((DIicBusChannelSlave*)((iCapturedChannel.iChanPtr)->GetChannelPtr()))->ReleaseChannel();
sl@0
  1320
    //After release channel, reset iCapturedChan
sl@0
  1321
    iCapturedChannel.iChanPtr = NULL;
sl@0
  1322
    iCapturedChannel.iChannelId = 0;
sl@0
  1323
#endif
sl@0
  1324
    return r;
sl@0
  1325
	}
sl@0
  1326
sl@0
  1327
void DChannelIicClient::DoCancel(TInt aMask)
sl@0
  1328
	{
sl@0
  1329
// Cancel an outstanding request.
sl@0
  1330
	CLIENT_PRINT(("DChannelIicClient::DoCancel invoked with aMask=0x%x\n", aMask));
sl@0
  1331
sl@0
  1332
	// inline void CancelAsyncOperation(TRequestStatus* aStatus, TInt aBusId)	{TInt* parms[2]; parms[0]=(TInt*)aStatus; parms[1]=(TInt*)aBusId;DoCancel((TInt)&parms[0]);}
sl@0
  1333
	// aMask has the address on TInt* parms[2]
sl@0
  1334
	// parms[0] = TRequestStatus pointer
sl@0
  1335
	// parms[1] = Bus Identifier
sl@0
  1336
	TInt* parms[2];
sl@0
  1337
	TInt r=Kern::ThreadRawRead(iClient,(TAny*)aMask,&(parms[0]),2*sizeof(TInt*));
sl@0
  1338
	if(r!=KErrNone)
sl@0
  1339
		{
sl@0
  1340
		CLIENT_PRINT(("DChannelIicClient::DoCancel ERROR - Can't read parms[]\n"));
sl@0
  1341
		return;	// Can't proceed if can't access request parameters
sl@0
  1342
		}
sl@0
  1343
	CLIENT_PRINT(("DChannelIicClient::DoCancel - TRequestStatus 0x%x, BusID = 0x%x\n",parms[0],parms[1]));
sl@0
  1344
sl@0
  1345
	TTransStatusPair* searchPair = new TTransStatusPair();
sl@0
  1346
	TTransCbPair* cbPair = new TTransCbPair();
sl@0
  1347
	searchPair->iReq = (TRequestStatus*)(parms[0]);
sl@0
  1348
sl@0
  1349
	GetWriteAccess();
sl@0
  1350
	Lock();
sl@0
  1351
sl@0
  1352
	TInt pairIndexByStatus = iTransStatArrayByStatus.FindInOrder(searchPair,TransStatusOrderByStatus);
sl@0
  1353
	CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByStatus=0x%x\n",pairIndexByStatus));
sl@0
  1354
	TInt pairIndexByTrans = KErrNotFound;
sl@0
  1355
sl@0
  1356
	if(pairIndexByStatus<0)
sl@0
  1357
		{
sl@0
  1358
		// If the TRequestStatus object is not found then either the value was invalid or
sl@0
  1359
		// the object may already have been completed.
sl@0
  1360
		FreeWriteAccess();
sl@0
  1361
		Unlock();
sl@0
  1362
		CLIENT_PRINT(("DChannelIicClient::DoCancel() - (status) FindInOrder returned %d (status=0x%x)\n",pairIndexByStatus,parms[0]));
sl@0
  1363
		}
sl@0
  1364
	else
sl@0
  1365
		{
sl@0
  1366
		// The status-transaction pair exists in the status-index array - so remove it
sl@0
  1367
		TTransStatusPair* pairPtrStatus = iTransStatArrayByStatus[pairIndexByStatus];
sl@0
  1368
		iTransStatArrayByStatus.Remove(pairIndexByStatus);
sl@0
  1369
sl@0
  1370
		pairIndexByTrans = iTransStatArrayByTrans.FindInOrder(pairPtrStatus,TransStatusOrderByTrans);
sl@0
  1371
		CLIENT_PRINT(("DChannelIicClient::DoCancel - pairIndexByTrans=0x%x\n",pairIndexByTrans));
sl@0
  1372
		if(pairIndexByTrans>=0)
sl@0
  1373
			{
sl@0
  1374
			iTransStatArrayByTrans.Remove(pairIndexByTrans);
sl@0
  1375
			}
sl@0
  1376
		FreeWriteAccess();
sl@0
  1377
		Unlock();
sl@0
  1378
sl@0
  1379
		CLIENT_PRINT(("DChannelIicClient::DoCancel pairPtrStatus=0x%x\n", pairPtrStatus));
sl@0
  1380
sl@0
  1381
		// Allow the bus to perform any required processing
sl@0
  1382
		TIicBusTransaction* trans = pairPtrStatus->iTrans;
sl@0
  1383
		CLIENT_PRINT(("DChannelIicClient::CancelTransaction - invoking with busId=0x%x, trans=0x%x\n",(TInt)(parms[1]),trans));
sl@0
  1384
		r = CancelTransaction((TInt)(parms[1]), trans);
sl@0
  1385
		cbPair->iTrans=trans;
sl@0
  1386
		TInt cbIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
sl@0
  1387
		TTransCbPair* theCbPair = iTransCbArrayByTrans[cbIndex];
sl@0
  1388
		TIicBusCallback* cb= (iTransCbArrayByTrans[cbIndex])->iCb;
sl@0
  1389
		iTransCbArrayByTrans.Remove(cbIndex);
sl@0
  1390
		
sl@0
  1391
		// Complete the TRequestStatus object according to the returned value
sl@0
  1392
		TRequestStatus* status= (TRequestStatus*)(parms[0]);
sl@0
  1393
		Kern::RequestComplete(iClient, status, r);
sl@0
  1394
sl@0
  1395
		// Clean up
sl@0
  1396
		delete cb;
sl@0
  1397
		delete theCbPair;
sl@0
  1398
		// We should call CleanupExtractTrans() to delete all the objects we created in ExtractTransData()
sl@0
  1399
		CleanupExtractTrans(trans);
sl@0
  1400
        CleanupTransaction(trans);  
sl@0
  1401
		delete pairPtrStatus;
sl@0
  1402
		}
sl@0
  1403
sl@0
  1404
	delete cbPair;
sl@0
  1405
	delete searchPair;
sl@0
  1406
sl@0
  1407
	return;
sl@0
  1408
	}
sl@0
  1409
sl@0
  1410
sl@0
  1411
// Function to support preamble testing
sl@0
  1412
void PreambleCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
sl@0
  1413
	{
sl@0
  1414
	CLIENT_PRINT(("IIC Client: PreambleCallbackFunc invoked\n"));
sl@0
  1415
	// aParam is the address of the client that created the transaction object
sl@0
  1416
	__ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("PreambleCallbackFunc, client address ==NULL",__LINE__));
sl@0
  1417
	DChannelIicClient *client = (DChannelIicClient*)aParam;
sl@0
  1418
	__ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("PreambleCallbackFunc, iClient==NULL",__LINE__));
sl@0
  1419
	__ASSERT_ALWAYS(client->iPreambleStatus!=NULL,Kern::Fault("PreambleCallbackFunc, iPreambleStatus==NULL",__LINE__));
sl@0
  1420
	Kern::RequestComplete(client->iClient, client->iPreambleStatus, KErrNone);
sl@0
  1421
	}
sl@0
  1422
sl@0
  1423
TIicBusTransaction* DChannelIicClient::iMultiTransac;
sl@0
  1424
sl@0
  1425
// Function to support multi transc testing
sl@0
  1426
TIicBusTransaction* DChannelIicClient::MultiTranscCallbackFunc(TIicBusTransaction* /*aTrans*/, TAny* aParam)
sl@0
  1427
	{
sl@0
  1428
	CLIENT_PRINT(("IIC Client: MultiTranscCallbackFunc invoked\n"));
sl@0
  1429
	// aParam is the address of the client that created the transaction object
sl@0
  1430
	__ASSERT_ALWAYS(aParam!=NULL,Kern::Fault("MultiTranscCallbackFunc, client address ==NULL",__LINE__));
sl@0
  1431
	DChannelIicClient *client = (DChannelIicClient*)aParam;
sl@0
  1432
	__ASSERT_ALWAYS(client->iClient!=NULL,Kern::Fault("MultiTranscCallbackFunc, iClient==NULL",__LINE__));
sl@0
  1433
	__ASSERT_ALWAYS(client->iMultiTranscStatus!=NULL,Kern::Fault("MultiTranscCallbackFunc, iMultiTranscStatus==NULL",__LINE__));
sl@0
  1434
	Kern::RequestComplete(client->iClient, client->iMultiTranscStatus, KErrNone);
sl@0
  1435
	return iMultiTransac;
sl@0
  1436
	}
sl@0
  1437
sl@0
  1438
TInt DChannelIicClient::CleanupExtractTrans(TIicBusTransaction* aTrans)
sl@0
  1439
	{
sl@0
  1440
	// Clean up the data created in ExtractTransData()
sl@0
  1441
	TExtractInfo *extractInfo = new TExtractInfo();
sl@0
  1442
	extractInfo->iTrans = aTrans;
sl@0
  1443
	TInt index = iExtractInfoArray.FindInOrder(extractInfo, ExtractInfoOrderByTrans);
sl@0
  1444
	if(index >= 0)
sl@0
  1445
	    {
sl@0
  1446
	    delete iExtractInfoArray[index];
sl@0
  1447
	    iExtractInfoArray.Remove(index);
sl@0
  1448
	    }
sl@0
  1449
	delete extractInfo;
sl@0
  1450
	return KErrNone;
sl@0
  1451
	}
sl@0
  1452
sl@0
  1453
TInt DChannelIicClient::ExtractTransData(TUsideTracnDesc* aUsideTrancnDesc, TIicBusTransaction*& aTrans)
sl@0
  1454
	{
sl@0
  1455
// Utility function to create a TIicBusTransaction object from the parameters passed by the user-side TUsideTracnDesc object
sl@0
  1456
sl@0
  1457
	TInt r = KErrNone;
sl@0
  1458
	TUsideTracnDesc usTrans;
sl@0
  1459
	r=Kern::ThreadRawRead(iClient,aUsideTrancnDesc,&usTrans,sizeof(TUsideTracnDesc));
sl@0
  1460
	if(r!=KErrNone)
sl@0
  1461
		{
sl@0
  1462
		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans\n"));
sl@0
  1463
		return KErrGeneral;	// Can't proceed if can't access request parameters
sl@0
  1464
		}
sl@0
  1465
	// Ensure pointers potentially used for allocation are NULL, to facilitate cleanup
sl@0
  1466
	iSpiBuf=NULL;
sl@0
  1467
	iI2cBuf=NULL;
sl@0
  1468
	iTfer=NULL;
sl@0
  1469
	iTransPreamble=NULL;
sl@0
  1470
	iFdTfer=NULL;
sl@0
  1471
sl@0
  1472
	// Get the header (depends on the bus type)
sl@0
  1473
	TBusType busType = usTrans.iType;
sl@0
  1474
	TConfigSpiBufV01 *spiBuf = NULL;
sl@0
  1475
	TConfigI2cBufV01 *i2cBuf = NULL;
sl@0
  1476
	// extractInfo is used to keep the bufPtr and tfer of the transaction,
sl@0
  1477
	// and will later be stored in iExtractInfoArray, sorting by transaction.
sl@0
  1478
	// The extractInfo object will be freed in CleanupExtractTrans.
sl@0
  1479
	TExtractInfo *extractInfo = new TExtractInfo();
sl@0
  1480
	TDes8* bufPtr=NULL;
sl@0
  1481
	if(busType == ESpi)
sl@0
  1482
		{
sl@0
  1483
		if((spiBuf = new TConfigSpiBufV01()) == NULL)
sl@0
  1484
			{
sl@0
  1485
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate spiBuf\n"));
sl@0
  1486
			return KErrNoMemory;
sl@0
  1487
			}
sl@0
  1488
		if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
sl@0
  1489
			{
sl@0
  1490
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to spiBuf\n"));
sl@0
  1491
			return KErrGeneral;
sl@0
  1492
			}
sl@0
  1493
		bufPtr=(TDes8*)spiBuf;
sl@0
  1494
		}
sl@0
  1495
	else if(busType == EI2c)
sl@0
  1496
		{
sl@0
  1497
		if((i2cBuf = new TConfigI2cBufV01()) == NULL)
sl@0
  1498
			{
sl@0
  1499
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unable to allocate i2cBuf\n"));
sl@0
  1500
			return KErrNoMemory;
sl@0
  1501
			}
sl@0
  1502
		if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *i2cBuf, 0, KChunkShiftBy0 ))!=KErrNone)
sl@0
  1503
			{
sl@0
  1504
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read usTrans.iHeader to i2cBuf\n"));
sl@0
  1505
			return KErrGeneral;
sl@0
  1506
			}
sl@0
  1507
		bufPtr=(TDes8*)i2cBuf;
sl@0
  1508
		}
sl@0
  1509
	else
sl@0
  1510
		{
sl@0
  1511
		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - unrecognised bus type\n"));
sl@0
  1512
		return KErrGeneral;
sl@0
  1513
		}
sl@0
  1514
	extractInfo->iBufPtr = bufPtr;
sl@0
  1515
	// Get the half-duplex transfer information
sl@0
  1516
	TUsideTferDesc* usTferPtr = usTrans.iHalfDuplexTrans;
sl@0
  1517
	TUsideTferDesc usTfer;
sl@0
  1518
	r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
sl@0
  1519
	if(r!=KErrNone)
sl@0
  1520
		{
sl@0
  1521
		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex usTfer\n"));
sl@0
  1522
		return KErrGeneral;	// Can't proceed if can't access request parameters
sl@0
  1523
		}
sl@0
  1524
	// Need to access the descriptor holding the information to be transferred
sl@0
  1525
	TBuf8 <MAX_TRANS_LENGTH> tferData;
sl@0
  1526
	r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,tferData,0,KChunkShiftBy0);
sl@0
  1527
	if(r!=KErrNone)
sl@0
  1528
		{
sl@0
  1529
		CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read half-duplex tferData\n"));
sl@0
  1530
		return KErrGeneral;	// Can't proceed if can't access request parameters
sl@0
  1531
		}
sl@0
  1532
sl@0
  1533
	TIicBusTransfer::TReqType type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
sl@0
  1534
	tfer7 = new TIicBusTransfer(type, usTfer.iBufGranularity, &tferData);
sl@0
  1535
	extractInfo->iTfer = tfer7;
sl@0
  1536
	// Construct the appropriate transaction object with the half-duplex information
sl@0
  1537
	TUint8 transFlags = usTrans.iFlags;
sl@0
  1538
sl@0
  1539
	if((transFlags&KTransactionWithPreamble)&&(transFlags&KTransactionWithMultiTransc))
sl@0
  1540
		{
sl@0
  1541
		if(usTrans.iPreambleArg == NULL)
sl@0
  1542
			{
sl@0
  1543
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
sl@0
  1544
			return KErrArgument;
sl@0
  1545
			}
sl@0
  1546
		if(usTrans.iMultiTranscArg == NULL)
sl@0
  1547
			{
sl@0
  1548
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - ExtTrans TRequestStatus==NULL\n"));
sl@0
  1549
			return KErrArgument;
sl@0
  1550
			}
sl@0
  1551
		iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
sl@0
  1552
		iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
sl@0
  1553
		TIicBusTransactionPreambleExt* transExt;
sl@0
  1554
sl@0
  1555
		transExt = new TIicBusTransactionPreambleExt(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this,
sl@0
  1556
							(TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
sl@0
  1557
		if(transExt == NULL)
sl@0
  1558
			{
sl@0
  1559
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
sl@0
  1560
			return KErrNoMemory;	// Can't proceed if can't access request parameters
sl@0
  1561
			}
sl@0
  1562
		aTrans = transExt;
sl@0
  1563
sl@0
  1564
		}
sl@0
  1565
	else if(transFlags & KTransactionWithPreamble)
sl@0
  1566
		{
sl@0
  1567
		// Preamble required - construct the derived-class transaction object
sl@0
  1568
		if(usTrans.iPreambleArg == NULL)
sl@0
  1569
			{
sl@0
  1570
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - preamble TRequestStatus==NULL\n"));
sl@0
  1571
			return KErrArgument;
sl@0
  1572
			}
sl@0
  1573
		iPreambleStatus = (TRequestStatus*)(usTrans.iPreambleArg);
sl@0
  1574
		TIicBusTransactionPreamble* TransPreamble;
sl@0
  1575
		TransPreamble = new TIicBusTransactionPreamble(bufPtr, tfer7, (TIicBusPreamble)(&PreambleCallbackFunc), this);
sl@0
  1576
		if(TransPreamble == NULL)
sl@0
  1577
			{
sl@0
  1578
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
sl@0
  1579
			return KErrNoMemory;	// Can't proceed if can't access request parameters
sl@0
  1580
			}
sl@0
  1581
		aTrans = TransPreamble;
sl@0
  1582
		}
sl@0
  1583
	else if(transFlags & KTransactionWithMultiTransc)
sl@0
  1584
		{
sl@0
  1585
		// Preamble required - construct the derived-class transaction object
sl@0
  1586
		if(usTrans.iMultiTranscArg == NULL)
sl@0
  1587
			{
sl@0
  1588
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Multi Transc TRequestStatus==NULL\n"));
sl@0
  1589
			return KErrArgument;
sl@0
  1590
			}
sl@0
  1591
		iMultiTranscStatus = (TRequestStatus*)(usTrans.iMultiTranscArg);
sl@0
  1592
		TIicBusTransactionMultiTransc* transMultiTransc;
sl@0
  1593
		transMultiTransc = new TIicBusTransactionMultiTransc(bufPtr, tfer7, (TIicBusMultiTranscCbFn)(&MultiTranscCallbackFunc), this);
sl@0
  1594
		if(transMultiTransc == NULL)
sl@0
  1595
			{
sl@0
  1596
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
sl@0
  1597
			return KErrNoMemory;	// Can't proceed if can't access request parameters
sl@0
  1598
			}
sl@0
  1599
		aTrans = transMultiTransc;
sl@0
  1600
		}
sl@0
  1601
	else
sl@0
  1602
		{
sl@0
  1603
		// Preamble not required
sl@0
  1604
		aTrans = new TIicBusTransaction(bufPtr, tfer7);
sl@0
  1605
		if(aTrans == NULL)
sl@0
  1606
			{
sl@0
  1607
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't create trans\n"));
sl@0
  1608
			return KErrNoMemory;	// Can't proceed if can't access request parameters
sl@0
  1609
			}
sl@0
  1610
		}
sl@0
  1611
sl@0
  1612
	// If full duplex transaction is required get that information, too
sl@0
  1613
	usTferPtr = usTrans.iFullDuplexTrans;
sl@0
  1614
	if(usTferPtr!=NULL)
sl@0
  1615
		{
sl@0
  1616
		r=Kern::ThreadRawRead(iClient,usTferPtr,&usTfer,sizeof(TUsideTferDesc));
sl@0
  1617
		if(r!=KErrNone)
sl@0
  1618
			{
sl@0
  1619
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex usTfer\n"));
sl@0
  1620
			return KErrGeneral;	// Can't proceed if can't access request parameters
sl@0
  1621
			}
sl@0
  1622
		// Need to access the descriptor holding the information to be transferred
sl@0
  1623
		TBuf8 <MAX_TRANS_LENGTH> fdTferData;
sl@0
  1624
		r=Kern::ThreadDesRead(iClient,usTfer.iBuffer,fdTferData,0,KChunkShiftBy0);
sl@0
  1625
		if(r!=KErrNone)
sl@0
  1626
			{
sl@0
  1627
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - Can't read full-duplex tferData\n"));
sl@0
  1628
			return KErrGeneral;	// Can't proceed if can't access request parameters
sl@0
  1629
			}
sl@0
  1630
sl@0
  1631
		type=(usTfer.iType == EMasterWrite)?TIicBusTransfer::EMasterWrite:TIicBusTransfer::EMasterRead;
sl@0
  1632
		r=aTrans->SetFullDuplexTrans(iFdTfer);
sl@0
  1633
		if(r!=KErrNone)
sl@0
  1634
			{
sl@0
  1635
			CLIENT_PRINT(("DChannelIicClient::ExtractTransData ERROR - SetFullDuplexTrans returned %d\n",r));
sl@0
  1636
			return r;
sl@0
  1637
			}
sl@0
  1638
		}
sl@0
  1639
	extractInfo->iTrans = aTrans;
sl@0
  1640
	iExtractInfoArray.InsertInOrder(extractInfo, ExtractInfoOrderByTrans);
sl@0
  1641
	return r;
sl@0
  1642
	}
sl@0
  1643
sl@0
  1644
#define KMaxTferTextLength 20
sl@0
  1645
#define KLongNodeTestLength 15
sl@0
  1646
#define KShortNodeTestLength 5
sl@0
  1647
_LIT(KFullTracnHdrText,"Full duplex test");		// length = 22
sl@0
  1648
#define KFullTracnHdrTextLength 16
sl@0
  1649
sl@0
  1650
sl@0
  1651
// Create transfer list with three nodes
sl@0
  1652
// All memories are allocated from the kernel heap and referenced by class members
sl@0
  1653
// DeleteFullDuplexTest should be called to release memory after use.
sl@0
  1654
// List created here will be assigned to iHalfDuplexTrans in TIicBusTransaction
sl@0
  1655
// If aNodeLength3 = 0, only return a 2 nodes transfer
sl@0
  1656
TInt DChannelIicClient::CreateTransferListHalfDuplex(
sl@0
  1657
			TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
sl@0
  1658
			TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
sl@0
  1659
			TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
sl@0
  1660
	{
sl@0
  1661
	buf1 = HBuf8::New(KMaxTferTextLength);
sl@0
  1662
	buf2 = HBuf8::New(KMaxTferTextLength);
sl@0
  1663
	buf3 = HBuf8::New(KMaxTferTextLength);
sl@0
  1664
	tfer1 = new TIicBusTransfer(aNodeDir1,8,buf1);
sl@0
  1665
	tfer2 = new TIicBusTransfer(aNodeDir2,8,buf2);
sl@0
  1666
	tfer3 = new TIicBusTransfer(aNodeDir3,8,buf3);
sl@0
  1667
sl@0
  1668
	if(buf1 == NULL||buf2 == NULL||buf3 == NULL||
sl@0
  1669
		tfer1 == NULL||tfer2 == NULL||tfer3 == NULL)
sl@0
  1670
		{
sl@0
  1671
		delete buf1; delete buf2; delete buf3;
sl@0
  1672
		delete tfer1; delete tfer2;	delete tfer3;
sl@0
  1673
		return KErrNoMemory;
sl@0
  1674
		}
sl@0
  1675
sl@0
  1676
	TInt i;
sl@0
  1677
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf1->Append('*');
sl@0
  1678
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf2->Append('*');
sl@0
  1679
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf3->Append('*');
sl@0
  1680
sl@0
  1681
	tfer1->LinkAfter(tfer2);
sl@0
  1682
sl@0
  1683
	//allow two nodes
sl@0
  1684
	if(aNodeLength3>0)
sl@0
  1685
		{
sl@0
  1686
		tfer2->LinkAfter(tfer3);
sl@0
  1687
		}
sl@0
  1688
sl@0
  1689
	return KErrNone;
sl@0
  1690
sl@0
  1691
	}
sl@0
  1692
sl@0
  1693
// Create transfer list with three nodes
sl@0
  1694
// All memories are allocated from the kernel heap and referenced by class members
sl@0
  1695
// DeleteFullDuplexTest should be called to release memory after use.
sl@0
  1696
// List created here will be assigned to iFullDuplexTrans in TIicBusTransaction
sl@0
  1697
// If aNodeLength3 = 0, only return a 2 nodes transfer
sl@0
  1698
TInt DChannelIicClient::CreateTransferListFullDuplex(
sl@0
  1699
			TIicBusTransfer::TReqType aNodeDir1, TInt aNodeLength1,
sl@0
  1700
			TIicBusTransfer::TReqType aNodeDir2, TInt aNodeLength2,
sl@0
  1701
			TIicBusTransfer::TReqType aNodeDir3, TInt aNodeLength3)
sl@0
  1702
	{
sl@0
  1703
	buf4 = HBuf8::New(KMaxTferTextLength);
sl@0
  1704
	buf5 = HBuf8::New(KMaxTferTextLength);
sl@0
  1705
	buf6 = HBuf8::New(KMaxTferTextLength);
sl@0
  1706
	tfer4 = new TIicBusTransfer(aNodeDir1,8,buf4);
sl@0
  1707
	tfer5 = new TIicBusTransfer(aNodeDir2,8,buf5);
sl@0
  1708
	tfer6 = new TIicBusTransfer(aNodeDir3,8,buf6);
sl@0
  1709
sl@0
  1710
	if(buf4 == NULL||buf5 == NULL||buf6 == NULL||
sl@0
  1711
		tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
sl@0
  1712
		{
sl@0
  1713
		delete buf4; delete buf5; delete buf6;
sl@0
  1714
		delete tfer4; delete tfer5;	delete tfer6;
sl@0
  1715
		return KErrNoMemory;
sl@0
  1716
		}
sl@0
  1717
sl@0
  1718
	TInt i;
sl@0
  1719
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength1); i++) buf4->Append('*');
sl@0
  1720
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength2); i++) buf5->Append('*');
sl@0
  1721
	for(i=0; (i<KMaxTferTextLength)&&(i<aNodeLength3); i++) buf6->Append('*');
sl@0
  1722
sl@0
  1723
	tfer4->LinkAfter(tfer5);
sl@0
  1724
sl@0
  1725
	//allow two nodes
sl@0
  1726
	if(aNodeLength3>0)
sl@0
  1727
		{
sl@0
  1728
		tfer5->LinkAfter(tfer6);
sl@0
  1729
		}
sl@0
  1730
sl@0
  1731
	return KErrNone;
sl@0
  1732
sl@0
  1733
	}
sl@0
  1734
sl@0
  1735
// Delete transaction and all allocated transfers and buffers
sl@0
  1736
TInt DChannelIicClient::DeleteFullDuplexTest(TIicBusTransaction *aTrans)
sl@0
  1737
	{
sl@0
  1738
	delete buf1; delete buf2; delete buf3;
sl@0
  1739
	delete tfer1; delete tfer2; delete tfer3;
sl@0
  1740
sl@0
  1741
	delete buf4; delete buf5; delete buf6;
sl@0
  1742
	delete tfer4; delete tfer5; delete tfer6;
sl@0
  1743
sl@0
  1744
	delete header;
sl@0
  1745
	delete aTrans;
sl@0
  1746
sl@0
  1747
	return KErrNone;
sl@0
  1748
	}
sl@0
  1749
sl@0
  1750
// Do full duplex creation test
sl@0
  1751
TInt DChannelIicClient::DoCreateFullDuplexTransTest(TInt aTestType)
sl@0
  1752
	{
sl@0
  1753
	CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest starts\n"));
sl@0
  1754
sl@0
  1755
	TInt r=KErrNone;
sl@0
  1756
	switch(aTestType)
sl@0
  1757
		{
sl@0
  1758
		case RBusDevIicClient::ETestValidFullDuplexTrans:
sl@0
  1759
			{
sl@0
  1760
			// equal length, opposite transfer direction
sl@0
  1761
			r = CreateTransferListHalfDuplex(
sl@0
  1762
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1763
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1764
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
sl@0
  1765
			if(r!=KErrNone) break;
sl@0
  1766
			r = CreateTransferListFullDuplex(
sl@0
  1767
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1768
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1769
						TIicBusTransfer::EMasterRead, KLongNodeTestLength);
sl@0
  1770
			if(r!=KErrNone) break;
sl@0
  1771
			break;
sl@0
  1772
			}
sl@0
  1773
		case RBusDevIicClient::ETestInvalidFullDuplexTrans1:
sl@0
  1774
			{
sl@0
  1775
			// equal length, same transfer direction
sl@0
  1776
			r = CreateTransferListHalfDuplex(
sl@0
  1777
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1778
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1779
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
sl@0
  1780
			if(r!=KErrNone) break;
sl@0
  1781
			r = CreateTransferListFullDuplex(
sl@0
  1782
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1783
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1784
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength);
sl@0
  1785
			if(r!=KErrNone) break;
sl@0
  1786
			break;
sl@0
  1787
			}
sl@0
  1788
		case RBusDevIicClient::ETestInvalidFullDuplexTrans2:
sl@0
  1789
			{
sl@0
  1790
			// different, opposite transfer direction
sl@0
  1791
			r = CreateTransferListHalfDuplex(
sl@0
  1792
						TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
sl@0
  1793
						TIicBusTransfer::EMasterRead, KShortNodeTestLength,
sl@0
  1794
						TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
sl@0
  1795
			if(r!=KErrNone) break;
sl@0
  1796
			r = CreateTransferListFullDuplex(
sl@0
  1797
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1798
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1799
						TIicBusTransfer::EMasterRead, KLongNodeTestLength);
sl@0
  1800
			if(r!=KErrNone) break;
sl@0
  1801
			break;
sl@0
  1802
			}
sl@0
  1803
		case RBusDevIicClient::ETestLastNodeFullDuplexTrans:
sl@0
  1804
			{
sl@0
  1805
			// different length for the last node
sl@0
  1806
			r = CreateTransferListHalfDuplex(
sl@0
  1807
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1808
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1809
						TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
sl@0
  1810
			if(r!=KErrNone) break;
sl@0
  1811
			r = CreateTransferListFullDuplex(
sl@0
  1812
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1813
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1814
						TIicBusTransfer::EMasterRead, KLongNodeTestLength);
sl@0
  1815
			if(r!=KErrNone) break;
sl@0
  1816
			break;
sl@0
  1817
			}
sl@0
  1818
		case RBusDevIicClient::ETestDiffNodeNoFullDuplexTrans:
sl@0
  1819
			{
sl@0
  1820
			// equal length, opposite transfer direction
sl@0
  1821
			r = CreateTransferListHalfDuplex(
sl@0
  1822
						TIicBusTransfer::EMasterWrite, KLongNodeTestLength,
sl@0
  1823
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1824
						TIicBusTransfer::EMasterWrite, KShortNodeTestLength);
sl@0
  1825
			if(r!=KErrNone) break;
sl@0
  1826
			r = CreateTransferListFullDuplex(
sl@0
  1827
						TIicBusTransfer::EMasterRead, KLongNodeTestLength,
sl@0
  1828
						TIicBusTransfer::EMasterWrite, KShortNodeTestLength,
sl@0
  1829
						TIicBusTransfer::EMasterRead, 0);
sl@0
  1830
			if(r!=KErrNone) break;
sl@0
  1831
			break;
sl@0
  1832
			}
sl@0
  1833
sl@0
  1834
sl@0
  1835
		default:
sl@0
  1836
			break;
sl@0
  1837
		}
sl@0
  1838
sl@0
  1839
	header = HBuf8::New(KFullTracnHdrTextLength);
sl@0
  1840
	TIicBusTransaction *Trans = new TIicBusTransaction(header,tfer1);
sl@0
  1841
sl@0
  1842
	if((r!=KErrNone) || (header == NULL) || (Trans == NULL))
sl@0
  1843
		{
sl@0
  1844
		CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest ERROR - failed to allocate the necessary memory\n"));
sl@0
  1845
		DeleteFullDuplexTest(Trans);
sl@0
  1846
		return KErrNoMemory;
sl@0
  1847
		}
sl@0
  1848
sl@0
  1849
	header->Copy(KFullTracnHdrText);
sl@0
  1850
sl@0
  1851
	TInt TestResult = Trans->SetFullDuplexTrans(tfer4);
sl@0
  1852
sl@0
  1853
	CLIENT_PRINT(("DChannelIicClient::DoCreateFullDuplexTransTest IIC after SetFullDuplexTrans TestResult =%d\n", TestResult));
sl@0
  1854
sl@0
  1855
	r = DeleteFullDuplexTest(Trans);
sl@0
  1856
sl@0
  1857
	return TestResult;
sl@0
  1858
sl@0
  1859
	}
sl@0
  1860
sl@0
  1861
sl@0
  1862
TInt DChannelIicClient::CreateDefaultSpiBuf(TConfigSpiBufV01*& aBuf)
sl@0
  1863
// Utility function to create a buffer for the SPI bus
sl@0
  1864
	{
sl@0
  1865
	TInt r=CreateSpiBuf(aBuf, ESpiWordWidth_8, 100000, ESpiPolarityLowRisingEdge, 100 ,ELittleEndian, EMsbFirst, 10, ESpiCSPinActiveLow);
sl@0
  1866
	return r;
sl@0
  1867
	}
sl@0
  1868
sl@0
  1869
// DoPriorityTest does the following actions:
sl@0
  1870
// 1. switch the bus (only use SPI test PSL) to priority test mode
sl@0
  1871
// 2. create 5 test transactions with different priorities and 1 blocking transaction
sl@0
  1872
// 3. enable blocking in test channel
sl@0
  1873
//     we can only block the test channel, we cannot suspend the bus controller
sl@0
  1874
// 3. send blocking transaction to the test channel
sl@0
  1875
//     the blocking transaction is just normal transaction.
sl@0
  1876
//     the test channel will be blocked once the first transaction is arrived
sl@0
  1877
// 4. send test transactions in opposite order to their priority
sl@0
  1878
// 5. unblock test channel
sl@0
  1879
// 6. read test result from channel
sl@0
  1880
// 7. switch the bus to normal mode
sl@0
  1881
TInt DChannelIicClient::DoPriorityTest(TInt aBusId)
sl@0
  1882
	{
sl@0
  1883
	TInt TestResult=KErrNone;
sl@0
  1884
	// Use the IIC StaticExtension interface to pass the request to the bus implementation
sl@0
  1885
	// To support testing, any values of aId for StaticExtension must be shifted left one place
sl@0
  1886
	TUint testId = ((TUint)(RBusDevIicClient::ECtlIoPriorityTest))<<1;
sl@0
  1887
	TInt r = KErrNone;
sl@0
  1888
sl@0
  1889
	r = StaticExtension(aBusId, testId, NULL, NULL);
sl@0
  1890
	__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1891
	if(r == KErrNone)
sl@0
  1892
		{
sl@0
  1893
		buf1 = HBuf8::New(1);
sl@0
  1894
		buf2 = HBuf8::New(1);
sl@0
  1895
		buf3 = HBuf8::New(1);
sl@0
  1896
		buf4 = HBuf8::New(1);
sl@0
  1897
		buf5 = HBuf8::New(1);
sl@0
  1898
		//buffer for blocking transaction
sl@0
  1899
		buf6 = HBuf8::New(1);
sl@0
  1900
sl@0
  1901
		if(buf1 == NULL||buf2 == NULL||buf3 == NULL||buf4 == NULL||buf5 == NULL||buf6 == NULL)
sl@0
  1902
			{
sl@0
  1903
			delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
sl@0
  1904
			r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  1905
			return KErrNoMemory;
sl@0
  1906
			}
sl@0
  1907
		tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
sl@0
  1908
		tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf2);
sl@0
  1909
		tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
sl@0
  1910
		tfer4 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf4);
sl@0
  1911
		tfer5 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf5);
sl@0
  1912
		//transfer for blocking transaction
sl@0
  1913
		tfer6 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf6);
sl@0
  1914
sl@0
  1915
		if(tfer1 == NULL||tfer2 == NULL||tfer3 == NULL||tfer4 == NULL||tfer5 == NULL||tfer6 == NULL)
sl@0
  1916
			{
sl@0
  1917
			delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
sl@0
  1918
			delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
sl@0
  1919
			r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  1920
			return KErrNoMemory;
sl@0
  1921
			}
sl@0
  1922
sl@0
  1923
		TConfigSpiBufV01* spiHeader1 = NULL;
sl@0
  1924
		TConfigSpiBufV01* spiHeader2 = NULL;
sl@0
  1925
		TConfigSpiBufV01* spiHeader3 = NULL;
sl@0
  1926
		TConfigSpiBufV01* spiHeader4 = NULL;
sl@0
  1927
		TConfigSpiBufV01* spiHeader5 = NULL;
sl@0
  1928
		TConfigSpiBufV01* spiHeaderBlock = NULL; 		//header for blocking transaction
sl@0
  1929
sl@0
  1930
sl@0
  1931
		TInt r = CreateDefaultSpiBuf(spiHeader1);
sl@0
  1932
		if(r == KErrNone)	r = CreateDefaultSpiBuf(spiHeader2);
sl@0
  1933
		if(r == KErrNone)	r = CreateDefaultSpiBuf(spiHeader3);
sl@0
  1934
		if(r == KErrNone)	r = CreateDefaultSpiBuf(spiHeader4);
sl@0
  1935
		if(r == KErrNone)	r = CreateDefaultSpiBuf(spiHeader5);
sl@0
  1936
		//header for blocking transaction
sl@0
  1937
		if(r == KErrNone)	r = CreateDefaultSpiBuf(spiHeaderBlock);
sl@0
  1938
sl@0
  1939
		if(r != KErrNone||spiHeader1 == NULL||spiHeader2 == NULL||spiHeader3 == NULL||spiHeader4 == NULL||spiHeader5 == NULL||spiHeaderBlock == NULL)
sl@0
  1940
			{
sl@0
  1941
			delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
sl@0
  1942
			delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
sl@0
  1943
			delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
sl@0
  1944
			r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  1945
			return KErrNoMemory;
sl@0
  1946
			}
sl@0
  1947
sl@0
  1948
		TIicBusTransaction* Transc1; Transc1 = new TIicBusTransaction(spiHeader1,tfer1, KPriorityTestPrio[0]);
sl@0
  1949
		TIicBusTransaction* Transc2; Transc2 = new TIicBusTransaction(spiHeader2,tfer2, KPriorityTestPrio[1]);
sl@0
  1950
		TIicBusTransaction* Transc3; Transc3 = new TIicBusTransaction(spiHeader3,tfer3, KPriorityTestPrio[2]);
sl@0
  1951
		TIicBusTransaction* Transc4; Transc4 = new TIicBusTransaction(spiHeader4,tfer4, KPriorityTestPrio[3]);
sl@0
  1952
		TIicBusTransaction* Transc5; Transc5 = new TIicBusTransaction(spiHeader5,tfer5, KPriorityTestPrio[4]);
sl@0
  1953
		//blocking transaction
sl@0
  1954
		TIicBusTransaction* TranscBlock; TranscBlock = new TIicBusTransaction(spiHeaderBlock,tfer6, KPriorityTestPrio[5]);
sl@0
  1955
sl@0
  1956
		if(Transc1 == NULL||Transc2 == NULL||Transc3 == NULL||Transc4 == NULL||Transc5 == NULL||TranscBlock == NULL)
sl@0
  1957
			{
sl@0
  1958
			delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
sl@0
  1959
			delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
sl@0
  1960
			delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
sl@0
  1961
			delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
sl@0
  1962
			r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  1963
			return KErrNoMemory;
sl@0
  1964
			}
sl@0
  1965
sl@0
  1966
		//dummy call back func is provided for asyn call
sl@0
  1967
		TIicBusCallback* cb = new TIicBusCallback(DummyCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
sl@0
  1968
sl@0
  1969
		// block the device channel. the channel will not be blocked until the first transaction arrive the channel
sl@0
  1970
		// To support testing, any values of aId for StaticExtension must be shifted left one place
sl@0
  1971
		TUint testId=((TUint)RBusDevIicClient::ECtlIoBlockReqCompletion)<<1;
sl@0
  1972
		r = StaticExtension(aBusId, testId, NULL, NULL);
sl@0
  1973
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1974
sl@0
  1975
		r = QueueTransaction(aBusId, TranscBlock, cb);  //send TranscBlock to block the channel
sl@0
  1976
		// send ordered transactions
sl@0
  1977
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1978
sl@0
  1979
		r = QueueTransaction(aBusId, Transc1, cb);
sl@0
  1980
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1981
		r = QueueTransaction(aBusId, Transc2, cb);
sl@0
  1982
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1983
		r = QueueTransaction(aBusId, Transc3, cb);
sl@0
  1984
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1985
		r = QueueTransaction(aBusId, Transc4, cb);
sl@0
  1986
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1987
		r = QueueTransaction(aBusId, Transc5, cb);
sl@0
  1988
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1989
sl@0
  1990
		// unblock device channel
sl@0
  1991
		testId=((TUint)RBusDevIicClient::ECtlIoUnblockReqCompletion)<<1;
sl@0
  1992
		r = StaticExtension(aBusId, testId, NULL, NULL);
sl@0
  1993
		__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  1994
sl@0
  1995
		#define KPriorityTestGetResultRetry 3
sl@0
  1996
		for(TInt i=0; i<KPriorityTestGetResultRetry ; i++)
sl@0
  1997
			{
sl@0
  1998
			NKern::Sleep(500);
sl@0
  1999
			testId=((TUint)RBusDevIicClient::EGetTestResult)<<1;
sl@0
  2000
			TestResult = StaticExtension(aBusId, testId, NULL, NULL);
sl@0
  2001
			if(TestResult!=KErrNotReady) break;
sl@0
  2002
			}
sl@0
  2003
sl@0
  2004
		cb->Cancel();
sl@0
  2005
		delete cb;
sl@0
  2006
		delete buf1; delete buf2; delete buf3; delete buf4; delete buf5; delete buf6;
sl@0
  2007
		delete tfer1; delete tfer2; delete tfer3; delete tfer4; delete tfer5; delete tfer6;
sl@0
  2008
		delete spiHeader1; delete spiHeader2; delete spiHeader3; delete spiHeader4; delete spiHeader5; delete spiHeaderBlock;
sl@0
  2009
		delete Transc1; delete Transc2; delete Transc3; delete Transc4; delete Transc5; delete TranscBlock;
sl@0
  2010
sl@0
  2011
		}
sl@0
  2012
	r = StaticExtension(aBusId, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  2013
	return TestResult;
sl@0
  2014
	}
sl@0
  2015
sl@0
  2016
TInt DChannelIicClient::ConstructTransactionOne(TIicBusTransaction*& aTrans)
sl@0
  2017
	{
sl@0
  2018
	// Transaction is to contain three transfers, with data defined by
sl@0
  2019
	// KTransOneTferOne[], KTransOneTferTwo[], KTransOneTferThree[]
sl@0
  2020
	buf1 = HBuf8::New(21);
sl@0
  2021
	buf2 = HBuf8::New(8);
sl@0
  2022
	buf3 = HBuf8::New(6);
sl@0
  2023
	tfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
sl@0
  2024
	tfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterRead,8,buf2);
sl@0
  2025
	tfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf3);
sl@0
  2026
	TInt r = CreateDefaultSpiBuf(spiHeader);
sl@0
  2027
	if((r != KErrNone)||(spiHeader == NULL)||(buf1 == NULL)||(buf2 == NULL)||(buf3 == NULL)||(tfer1 == NULL)||(tfer2 == NULL)||(tfer3 == NULL))
sl@0
  2028
		{
sl@0
  2029
		CLIENT_PRINT(("DChannelIicClient::ConstructTransactionOne ERROR - failed to allocate the necessary memory\n"));
sl@0
  2030
		delete buf1;
sl@0
  2031
		delete buf2;
sl@0
  2032
		delete buf3;
sl@0
  2033
		delete tfer1;
sl@0
  2034
		delete tfer2;
sl@0
  2035
		delete tfer3;
sl@0
  2036
		delete spiHeader;
sl@0
  2037
		delete aTrans;
sl@0
  2038
		return KErrNoMemory;
sl@0
  2039
		}
sl@0
  2040
	aTrans = new TIicBusTransaction(spiHeader,tfer1);
sl@0
  2041
	buf1->Copy(&(KTransOneTferOne[0]),21);
sl@0
  2042
	buf2->Copy(&(KTransOneTferTwo[0]),8);
sl@0
  2043
	buf3->Copy(&(KTransOneTferThree[0]),6);
sl@0
  2044
	tfer1->LinkAfter(tfer2);
sl@0
  2045
	tfer2->LinkAfter(tfer3);
sl@0
  2046
	return KErrNone;
sl@0
  2047
	}
sl@0
  2048
sl@0
  2049
void DChannelIicClient::CleanupTransactionOne(TIicBusTransaction*& aTrans)
sl@0
  2050
	{
sl@0
  2051
	// Release the allocated memory
sl@0
  2052
	delete buf1;
sl@0
  2053
	buf1=NULL;
sl@0
  2054
	delete buf2;
sl@0
  2055
	buf2=NULL;
sl@0
  2056
	delete buf3;
sl@0
  2057
	buf3=NULL;
sl@0
  2058
	delete tfer1;
sl@0
  2059
	tfer1=NULL;
sl@0
  2060
	delete tfer2;
sl@0
  2061
	tfer2=NULL;
sl@0
  2062
	delete tfer3;
sl@0
  2063
	tfer3=NULL;
sl@0
  2064
	delete spiHeader;
sl@0
  2065
	spiHeader=NULL;
sl@0
  2066
	delete aTrans;
sl@0
  2067
	aTrans=NULL;
sl@0
  2068
	}
sl@0
  2069
sl@0
  2070
sl@0
  2071
void DChannelIicClient::CleanupTransaction(TIicBusTransaction*& aTrans)
sl@0
  2072
	{
sl@0
  2073
	delete iSpiBuf;
sl@0
  2074
	iSpiBuf=NULL;
sl@0
  2075
	delete iI2cBuf;
sl@0
  2076
	iI2cBuf=NULL;
sl@0
  2077
	TIicBusTransfer* currTfer = iTfer;
sl@0
  2078
	TIicBusTransfer* nextTfer = NULL;
sl@0
  2079
	while(currTfer)
sl@0
  2080
		{
sl@0
  2081
		TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
sl@0
  2082
		delete currTfer;
sl@0
  2083
		if(nextTfer)
sl@0
  2084
			currTfer = nextTfer;
sl@0
  2085
		else
sl@0
  2086
			currTfer = NULL;
sl@0
  2087
		};
sl@0
  2088
	iTfer=NULL;
sl@0
  2089
	currTfer = iFdTfer;
sl@0
  2090
	nextTfer = NULL;
sl@0
  2091
	while(currTfer)
sl@0
  2092
		{
sl@0
  2093
		TIicBusTransfer* nextTfer = (TIicBusTransfer*)(currTfer->Next());
sl@0
  2094
		delete currTfer;
sl@0
  2095
		if(nextTfer)
sl@0
  2096
			currTfer = nextTfer;
sl@0
  2097
		else
sl@0
  2098
			currTfer = NULL;
sl@0
  2099
		};
sl@0
  2100
	iFdTfer=NULL;
sl@0
  2101
	if(aTrans!=NULL)
sl@0
  2102
		{
sl@0
  2103
		delete aTrans;
sl@0
  2104
		aTrans=NULL;
sl@0
  2105
		}
sl@0
  2106
	if(iTransPreamble!=NULL)
sl@0
  2107
		{
sl@0
  2108
		delete iTransPreamble;
sl@0
  2109
		iTransPreamble=NULL;
sl@0
  2110
		}
sl@0
  2111
	}
sl@0
  2112
sl@0
  2113
void DChannelIicClient::TransModifCallback(TIicBusTransaction* /*aTrans*/, TInt /*aBusId*/, TInt aResult, TAny* aParam)
sl@0
  2114
	{
sl@0
  2115
	// Callback function used to test re-use of transaction and transfer buffers
sl@0
  2116
	// aParam is the address of the simulated client driver
sl@0
  2117
	DChannelIicClient* channel = (DChannelIicClient*)aParam;
sl@0
  2118
	TTransBufReuseData* reuseData = &(channel->iTransBufReuseData);
sl@0
  2119
sl@0
  2120
	// Since the transaction is no longer queued, should be able to modify the transfer and transaction content
sl@0
  2121
	channel->TestTransModification(reuseData->iTransaction, reuseData->iHdTfer, reuseData->iFdTfer, reuseData->iHdr);
sl@0
  2122
sl@0
  2123
	// Complete the user's request, delete objects allocated for this test and return
sl@0
  2124
	Kern::RequestComplete(channel->iClient, channel->iStatus, aResult);
sl@0
  2125
	delete reuseData->iCallback;	// Must do this before deleting the Transaction, in CleanupTransaction
sl@0
  2126
	channel->CleanupTransaction(channel->iTrans);
sl@0
  2127
	return;
sl@0
  2128
	}
sl@0
  2129
sl@0
  2130
sl@0
  2131
void DChannelIicClient::TestTransModification(TIicBusTransaction* aTransaction,
sl@0
  2132
											  TIicBusTransfer* aHdTfer,
sl@0
  2133
											  TIicBusTransfer* aFdTfer,
sl@0
  2134
											  TDes8* aHdr)
sl@0
  2135
	{
sl@0
  2136
	// Function to test that the content of Transaction and Transfer objects can be modified
sl@0
  2137
	// This assumes that the Transaction is in the appropriate state (EFree) - otherwise, the code will assert
sl@0
  2138
	// This function also assumes that transaction has aleady added the half-duplex and full-duplex transfers
sl@0
  2139
	// that are passed in as arguments, and that the transfers lists are non-NULL
sl@0
  2140
	// The original type of the transfers (read, write) are ignored, since it is not of interest in this test -
sl@0
  2141
	// instead, what is important is to ensure that the half-duplex and full-duplex transfer types are in opposing
sl@0
  2142
	// directions - so the types are explicitly set in this test.
sl@0
  2143
	//
sl@0
  2144
	TDes8* origBuf = NULL;
sl@0
  2145
	TInt8 origGranularity = 0;
sl@0
  2146
sl@0
  2147
	// Create a buffer for use in this function
sl@0
  2148
	_LIT(temporaryText,"Temporary Text");
sl@0
  2149
	TBuf8<15> tempBuf_8;
sl@0
  2150
	tempBuf_8.Copy(temporaryText);
sl@0
  2151
sl@0
  2152
	// Test modification of the two transfer lists while still part of the transaction
sl@0
  2153
	origBuf = (TDes8*)(aHdTfer->GetBuffer());
sl@0
  2154
	origGranularity = aHdTfer->WordWidth();
sl@0
  2155
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
sl@0
  2156
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
sl@0
  2157
sl@0
  2158
	origBuf = (TDes8*)(aFdTfer->GetBuffer());
sl@0
  2159
	origGranularity = aFdTfer->WordWidth();
sl@0
  2160
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
sl@0
  2161
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
sl@0
  2162
sl@0
  2163
	// Test transfers can be removed from the transaction
sl@0
  2164
	aTransaction->RemoveHalfDuplexTrans();
sl@0
  2165
	aTransaction->RemoveFullDuplexTrans();
sl@0
  2166
sl@0
  2167
	// Test modification of the two transfer lists while not part of a transaction
sl@0
  2168
	origBuf = (TDes8*)(aHdTfer->GetBuffer());
sl@0
  2169
	origGranularity = aHdTfer->WordWidth();
sl@0
  2170
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
sl@0
  2171
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
sl@0
  2172
sl@0
  2173
	origBuf = (TDes8*)(aFdTfer->GetBuffer());
sl@0
  2174
	origGranularity = aFdTfer->WordWidth();
sl@0
  2175
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
sl@0
  2176
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
sl@0
  2177
sl@0
  2178
	// Test transfers can be re-added to the transaction
sl@0
  2179
	aTransaction->SetHalfDuplexTrans(aHdr,aHdTfer);
sl@0
  2180
	aTransaction->SetFullDuplexTrans(aFdTfer);
sl@0
  2181
sl@0
  2182
	// Test modification of the two transfer lists now re-added to the transaction
sl@0
  2183
	origBuf = (TDes8*)(aHdTfer->GetBuffer());
sl@0
  2184
	origGranularity = aHdTfer->WordWidth();
sl@0
  2185
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, &tempBuf_8);
sl@0
  2186
	aHdTfer->SetTransferData(TIicBusTransfer::EMasterRead, origGranularity, origBuf);
sl@0
  2187
sl@0
  2188
	origBuf = (TDes8*)(aFdTfer->GetBuffer());
sl@0
  2189
	origGranularity = aFdTfer->WordWidth();
sl@0
  2190
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, &tempBuf_8);
sl@0
  2191
	aFdTfer->SetTransferData(TIicBusTransfer::EMasterWrite, origGranularity, origBuf);
sl@0
  2192
sl@0
  2193
	return;
sl@0
  2194
	}
sl@0
  2195
sl@0
  2196
TInt DChannelIicClient::DoControl(TInt aId, TAny* a1, TAny* a2)
sl@0
  2197
	{
sl@0
  2198
	CLIENT_PRINT(("DChannelIicClient::DoControl invoked with aId=0x%x, a1=0x%x, a2=0x%x\n", aId,a1,a2));
sl@0
  2199
	TInt r=KErrNone;
sl@0
  2200
	// To support testing, any values of aId for StaticExtension must be shifted left one place
sl@0
  2201
	// and for a Slave tests, the two msbs must be zero
sl@0
  2202
	TInt ctrlIoVal = 0;
sl@0
  2203
	if((aId & KTestMasterControlIo) == KTestMasterControlIo)
sl@0
  2204
		ctrlIoVal = (aId << 1);
sl@0
  2205
	if((aId & KTestSlaveControlIo) == KTestSlaveControlIo)
sl@0
  2206
		ctrlIoVal = (aId << 1) & 0x3FFFFFFF;
sl@0
  2207
	switch(aId)
sl@0
  2208
		{
sl@0
  2209
		case(RBusDevIicClient::EQTransSync):
sl@0
  2210
			{
sl@0
  2211
			// a1 specifies Bus Realisation Config to use
sl@0
  2212
			// a2 is a pointer to TUsideTracnDesc
sl@0
  2213
			TIicBusTransaction* trans = NULL;
sl@0
  2214
			TIicBusTransfer* tfer = NULL;
sl@0
  2215
			TConfigSpiBufV01 *spiBuf = NULL;
sl@0
  2216
			
sl@0
  2217
			//Read the transaction header to determin if it is a multi-transaction type
sl@0
  2218
			TUsideTracnDesc usTrans;
sl@0
  2219
sl@0
  2220
			if((Kern::ThreadRawRead(iClient,a2,&usTrans,sizeof(TUsideTracnDesc)))!=KErrNone)
sl@0
  2221
				{
sl@0
  2222
				CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
sl@0
  2223
				return KErrGeneral;
sl@0
  2224
				}
sl@0
  2225
sl@0
  2226
			if((usTrans.iFlags)&KTransactionWithMultiTransc)
sl@0
  2227
				{
sl@0
  2228
				// Since we are testing a multi-transaction, create another transaction object iMultiTransac,
sl@0
  2229
				// to represent the delayed part of the multi-transaction. After the preliminary
sl@0
  2230
				// transaction(passed from t_iic, with one read transfer) has been performed, 
sl@0
  2231
				// the IIC code will find that it is part of a 
sl@0
  2232
				// multi-transaction; it will call the callback for the transaction(set as MultiTranscCallbackFunc,
sl@0
  2233
				// in ExtractTransData) and this will return a pointer to the next part of the multi-transaction
sl@0
  2234
				// to be performed(iMultiTransac). It will then immediately pass this transaction object
sl@0
  2235
				// to the PSL for processing - before considering any other transactions that have been 
sl@0
  2236
				// requested, and without completing the multi-transaction request(this is done once 
sl@0
  2237
				// iMultiTransac has been processed)
sl@0
  2238
				buf1 = HBuf8::New(1);
sl@0
  2239
				spiBuf = new TConfigSpiBufV01();
sl@0
  2240
				if(buf1 == NULL||spiBuf == NULL) {delete buf1;delete spiBuf; return KErrNoMemory;}
sl@0
  2241
sl@0
  2242
sl@0
  2243
				if((r=Kern::ThreadDesRead(iClient, usTrans.iHeader, *spiBuf, 0, KChunkShiftBy0 ))!=KErrNone)
sl@0
  2244
					{
sl@0
  2245
					CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - Can't read iHeader to spiBuf\n"));
sl@0
  2246
					return KErrGeneral;
sl@0
  2247
					}
sl@0
  2248
sl@0
  2249
				tfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite,8,buf1);
sl@0
  2250
				if(tfer == NULL) {delete buf1; delete spiBuf; return KErrNoMemory;}
sl@0
  2251
sl@0
  2252
				iMultiTransac = new TIicBusTransaction((TDes8*)spiBuf, tfer);
sl@0
  2253
				if(iMultiTransac == NULL) {delete buf1; delete spiBuf; delete tfer; return KErrNoMemory;}
sl@0
  2254
				}
sl@0
  2255
			r = ExtractTransData((TUsideTracnDesc*)a2, trans);
sl@0
  2256
			if(r!=KErrNone)
sl@0
  2257
				{
sl@0
  2258
				CLIENT_PRINT(("DChannelIicClient::DoControl ERROR - ExtractTransData returned %d\n",r));
sl@0
  2259
				return r;
sl@0
  2260
				}
sl@0
  2261
			CLIENT_PRINT(("DChannelIicClient::DoControl invoking (synchronous) QueueTransaction with busId=0x%x, trans=0x%x\n",(TUint32)a1,trans));
sl@0
  2262
sl@0
  2263
			r = QueueTransaction((TUint32)a1, trans);
sl@0
  2264
			CleanupExtractTrans(trans);
sl@0
  2265
			CleanupTransaction(trans);
sl@0
  2266
			if((usTrans.iFlags)&KTransactionWithMultiTransc)
sl@0
  2267
				{
sl@0
  2268
				delete buf1;
sl@0
  2269
				delete spiBuf;
sl@0
  2270
				delete tfer;
sl@0
  2271
				delete iMultiTransac;
sl@0
  2272
				}
sl@0
  2273
			break;
sl@0
  2274
			}
sl@0
  2275
		case(RBusDevIicClient::ECtlIoBlockReqCompletion):
sl@0
  2276
		case(RBusDevIicClient::ECtlIoUnblockReqCompletion):
sl@0
  2277
		case(RBusDevIicClient::ECtlIoDeRegChan):
sl@0
  2278
			{
sl@0
  2279
			// a1 specifies Bus Realisation Config to use
sl@0
  2280
			CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
sl@0
  2281
			// Use the IIC StaticExtension interface to pass the request to the bus implementation
sl@0
  2282
			r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
sl@0
  2283
			break;
sl@0
  2284
			}
sl@0
  2285
		case(RBusDevIicClient::ECtlIoTestFullDuplexTrans):
sl@0
  2286
			{
sl@0
  2287
			// a1 specifies Bus Realisation Config to use
sl@0
  2288
			CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
sl@0
  2289
			r = DoCreateFullDuplexTransTest((TInt)a2);
sl@0
  2290
			break;
sl@0
  2291
			}
sl@0
  2292
		case(RBusDevIicClient::ECtlIoPriorityTest):
sl@0
  2293
			{
sl@0
  2294
			// a1 specifies Bus Realisation Config to use
sl@0
  2295
			CLIENT_PRINT(("DChannelIicClient::DoControl invoking StaticExtension with aId=%d, busId=0x%x\n",aId,(TUint32)a1));
sl@0
  2296
			r = DoPriorityTest((TUint32)a1);
sl@0
  2297
			break;
sl@0
  2298
			}
sl@0
  2299
sl@0
  2300
		case(RBusDevIicClient::ECtlIoTracnOne):
sl@0
  2301
			{
sl@0
  2302
			// a1 specifies Bus Realisation Config to use
sl@0
  2303
			CLIENT_PRINT(("DChannelIicClient::StaticExtension invoking StaticExtension with ctrlIoVal=%d, busId=0x%x\n",aId,(TUint32)a1));
sl@0
  2304
			// Use the IIC StaticExtension interface to pass the request to the bus implementation
sl@0
  2305
			r = StaticExtension((TUint32)a1, (TUint)ctrlIoVal, NULL, NULL);
sl@0
  2306
			__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("StaticExtension",__LINE__));
sl@0
  2307
			if(r == KErrNone)
sl@0
  2308
				{
sl@0
  2309
				// Create then send (synchronously) Transaction One
sl@0
  2310
				r = ConstructTransactionOne(iTrans);
sl@0
  2311
				__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  2312
				r = QueueTransaction((TUint32)a1, iTrans);
sl@0
  2313
				__ASSERT_ALWAYS(r == KErrNone,Kern::Fault("DoControl",__LINE__));
sl@0
  2314
				CleanupTransactionOne(iTrans);
sl@0
  2315
				}
sl@0
  2316
			r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  2317
			break;
sl@0
  2318
			}
sl@0
  2319
		case(RBusDevIicClient::ECtlIoSetTimeOutFlag):
sl@0
  2320
			{
sl@0
  2321
			CLIENT_PRINT(("DChannelIicClient::DoControl instruct the bus that it is to simulate a slave timeout"));
sl@0
  2322
			// To support testing, function index passed to StaticExtension must be shifted one place to the left
sl@0
  2323
			TUint testIndex = ((TUint)RBusDevIicClient::ECtlIoSetTimeOutFlag)<<1;;
sl@0
  2324
			r = StaticExtension((TUint32)a1, testIndex, NULL, NULL);
sl@0
  2325
			break;
sl@0
  2326
			}
sl@0
  2327
		case(RBusDevIicClient::ECtlIoNone):
sl@0
  2328
			{
sl@0
  2329
			CLIENT_PRINT(("DChannelIicClient::DoControl Return the bus to its default test state"));
sl@0
  2330
			r = StaticExtension((TUint32)a1, (TUint)RBusDevIicClient::ECtlIoNone, NULL, NULL);
sl@0
  2331
			break;
sl@0
  2332
			}
sl@0
  2333
sl@0
  2334
// Support for MasterSlave processing
sl@0
  2335
sl@0
  2336
		case(RBusDevIicClient::ECaptureChanSync):
sl@0
  2337
			{
sl@0
  2338
			// a1 is a pointer to the TDes8* aConfigHdr
sl@0
  2339
			// a2 is a pointer to TInt* parms[2], where:
sl@0
  2340
			// parms[0]=(TInt*)aBusId;
sl@0
  2341
			// parms[1]=&aChannelId;
sl@0
  2342
			//
sl@0
  2343
			TInt* parms[2];
sl@0
  2344
			r=Kern::ThreadRawRead(iClient,a2,&(parms[0]),2*sizeof(TInt*));
sl@0
  2345
			if(r!=KErrNone)
sl@0
  2346
				break;	// Can't proceed if can't access request parameters
sl@0
  2347
			//
sl@0
  2348
		  	TInt hdrSize = Kern::ThreadGetDesLength(iClient,a1);
sl@0
  2349
			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl hdrSize = 0x%x\n",hdrSize));
sl@0
  2350
  			if (hdrSize<=0)
sl@0
  2351
				{
sl@0
  2352
				CLIENT_PRINT(("DChannelIicSlaveClient::DoControl ERROR, hdrSize is invalid\n"));
sl@0
  2353
 				return KErrArgument;
sl@0
  2354
				}
sl@0
  2355
			if((iConfigHdr = HBuf8::New(hdrSize)) == NULL)
sl@0
  2356
				return KErrNoMemory;
sl@0
  2357
			r = Kern::ThreadDesRead(iClient,a1,*iConfigHdr,0);
sl@0
  2358
			if(r!=KErrNone)
sl@0
  2359
				{
sl@0
  2360
				delete iConfigHdr;
sl@0
  2361
				return r;
sl@0
  2362
				}
sl@0
  2363
			// Store the address of the user-side variable to update with the ChannelId
sl@0
  2364
			iClientChanId=parms[1];
sl@0
  2365
sl@0
  2366
			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking (synchronous) CaptureChannel\n"));
sl@0
  2367
			r = CaptureChannel((TInt)(parms[0]), iConfigHdr, iNotif, iChannelId);
sl@0
  2368
			if(r != KErrNone)
sl@0
  2369
			    delete iConfigHdr;
sl@0
  2370
			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl CaptureChannelgave iChannelId=0x%x\n",iChannelId));
sl@0
  2371
sl@0
  2372
			TInt r=Kern::ThreadRawWrite(iClient,iClientChanId,&iChannelId,sizeof(TInt));
sl@0
  2373
			(void)r;	// Silence the compiler
sl@0
  2374
sl@0
  2375
			break;
sl@0
  2376
			}
sl@0
  2377
sl@0
  2378
		case(RBusDevIicClient::EReleaseChan):
sl@0
  2379
			{
sl@0
  2380
			// a1 represents TInt aChannelId
sl@0
  2381
			CLIENT_PRINT(("DChannelIicSlaveClient::DoControl invoking ReleaseChannel\n"));
sl@0
  2382
			r = ReleaseChannel((TInt)a1);
sl@0
  2383
			delete iConfigHdr;
sl@0
  2384
			break;
sl@0
  2385
			}
sl@0
  2386
sl@0
  2387
		case(RBusDevIicClient::EInitSlaveClient):
sl@0
  2388
			{
sl@0
  2389
			r=InitSlaveClient();
sl@0
  2390
			break;
sl@0
  2391
			}
sl@0
  2392
		
sl@0
  2393
#ifdef STANDALONE_CHANNEL		
sl@0
  2394
        case(RBusDevIicClient::ETestIicChannelInlineFunc):
sl@0
  2395
            {  
sl@0
  2396
            TTestIicChannelInterface channelInterface(DIicBusChannel::EMaster, DIicBusChannel::EI2c, DIicBusChannel::EHalfDuplex);
sl@0
  2397
            r = channelInterface.TestInterface();
sl@0
  2398
            break;         
sl@0
  2399
            }
sl@0
  2400
#endif
sl@0
  2401
        
sl@0
  2402
        default:
sl@0
  2403
			{
sl@0
  2404
			CLIENT_PRINT(("DChannelIicClient::DoControl - unrecognised value for aId=0x%x\n",aId));
sl@0
  2405
			r=KErrArgument;
sl@0
  2406
			break;
sl@0
  2407
			}
sl@0
  2408
		}
sl@0
  2409
	return r;
sl@0
  2410
	}
sl@0
  2411
sl@0
  2412
TInt DChannelIicClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
sl@0
  2413
	{
sl@0
  2414
	CLIENT_PRINT(("DChannelIicClient::DoRequest invoked with aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n", aId,aStatus,a1,a2));
sl@0
  2415
sl@0
  2416
	TInt r=KErrNone;
sl@0
  2417
	switch(aId)
sl@0
  2418
		{
sl@0
  2419
		case(RBusDevIicClient::EQTransAsync):
sl@0
  2420
			{
sl@0
  2421
			// a1 specifies Bus Realisation Config to use
sl@0
  2422
			// a2 is a pointer to TIicBusTransaction
sl@0
  2423
			TIicBusTransaction* trans = NULL;
sl@0
  2424
			r = ExtractTransData((TUsideTracnDesc*)a2, trans);
sl@0
  2425
			if(r!=KErrNone)
sl@0
  2426
				{
sl@0
  2427
				CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - ExtractTransData returned %d\n",r));
sl@0
  2428
				return r;
sl@0
  2429
				}
sl@0
  2430
			// Create TIicBusCallback object
sl@0
  2431
			TIicBusCallback* cb = new TIicBusCallback(AsyncCallbackFunc, this, iDfcQue, 5); // 5 arbitrary
sl@0
  2432
			TTransCbPair* cbPair = new TTransCbPair();
sl@0
  2433
			cbPair->iCb=cb;
sl@0
  2434
			cbPair->iTrans=trans;
sl@0
  2435
			// Create an entry in the RPointerArray for TRequestStatus - TIicBusTransaction pairs
sl@0
  2436
			TTransStatusPair* pair = new TTransStatusPair();
sl@0
  2437
			pair->iReq=aStatus;
sl@0
  2438
			pair->iTrans=trans;
sl@0
  2439
			r=InsertPairs(pair,cbPair);
sl@0
  2440
			if(r!=KErrNone)
sl@0
  2441
				{
sl@0
  2442
				CLIENT_PRINT(("DChannelIicClient::DoRequest ERROR - InsertInOrder returned %d\n",r));
sl@0
  2443
				return r;
sl@0
  2444
				}
sl@0
  2445
			CLIENT_PRINT(("DChannelIicClient::DoRequest invoking (asynchronous) QueueTransaction with busId=0x%x, trans=0x%x, cb=0x%x\n",(TUint32)a1,trans,cb));
sl@0
  2446
			r = QueueTransaction((TUint32)a1, trans, cb);
sl@0
  2447
			if(r!=KErrNone)
sl@0
  2448
				{
sl@0
  2449
				// The transaction was not queued - since it will not be completed asynchronously, need to remove it here
sl@0
  2450
				GetWriteAccess();
sl@0
  2451
				Lock();
sl@0
  2452
				TInt pairIndex=iTransStatArrayByTrans.FindInOrder(pair,TransStatusOrderByTrans);
sl@0
  2453
				__ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByTrans pairIndex<0",__LINE__));
sl@0
  2454
				iTransStatArrayByTrans.Remove(pairIndex);
sl@0
  2455
				pairIndex = iTransStatArrayByStatus.FindInOrder(pair,TransStatusOrderByStatus);
sl@0
  2456
				__ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync ByStatus pairIndex<0",__LINE__));
sl@0
  2457
				iTransStatArrayByStatus.Remove(pairIndex);
sl@0
  2458
				pairIndex = iTransCbArrayByTrans.FindInOrder(cbPair,TransCbOrderByTrans);
sl@0
  2459
				__ASSERT_ALWAYS(pairIndex>=0,Kern::Fault("IIC Client, DoRequest, EQTransAsync Cb by Trans pairIndex<0",__LINE__));
sl@0
  2460
				iTransCbArrayByTrans.Remove(pairIndex);
sl@0
  2461
				FreeWriteAccess();
sl@0
  2462
				Unlock();
sl@0
  2463
				Kern::RequestComplete(iClient, aStatus, r);
sl@0
  2464
				delete cb;
sl@0
  2465
				delete cbPair;
sl@0
  2466
				CleanupExtractTrans(pair->iTrans);
sl@0
  2467
				CleanupTransaction(pair->iTrans);			
sl@0
  2468
				delete pair;
sl@0
  2469
				}
sl@0
  2470
			break;
sl@0
  2471
			}
sl@0
  2472
sl@0
  2473
		case(RBusDevIicClient::ECtrlIoTestBufReUse):
sl@0
  2474
			{
sl@0
  2475
			iStatus = aStatus;
sl@0
  2476
			// a1 specifies Bus Realisation Config to use
sl@0
  2477
sl@0
  2478
			// Ensure object pointers are made available
sl@0
  2479
			CleanupTransaction(iTrans);
sl@0
  2480
sl@0
  2481
			TInt r = KErrNone;
sl@0
  2482
			TIicBusCallback* cb = NULL;
sl@0
  2483
sl@0
  2484
			// Use default constructor to create an empty transaction
sl@0
  2485
			iTrans = new TIicBusTransaction();
sl@0
  2486
			if(iTrans == NULL)
sl@0
  2487
				{
sl@0
  2488
				CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTrans=NULL\n"));
sl@0
  2489
				r = KErrNoMemory;
sl@0
  2490
				}
sl@0
  2491
sl@0
  2492
			// Create a header for the transaction
sl@0
  2493
			if(r == KErrNone)
sl@0
  2494
				{
sl@0
  2495
				r = CreateDefaultSpiBuf(iSpiBuf);
sl@0
  2496
				if(r != KErrNone)
sl@0
  2497
					{
sl@0
  2498
					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - CreateDefaultSpiBuf returned %d\n",r));
sl@0
  2499
					}
sl@0
  2500
				}
sl@0
  2501
sl@0
  2502
			// Create and add transfer lists for half-duplex and full-duplex entries in the transaction
sl@0
  2503
			if(r == KErrNone)
sl@0
  2504
				{
sl@0
  2505
				// Use simple text as payload, 8bit granularity, half-duplex write, full-duplex read (ie payload ignored)
sl@0
  2506
				_LIT(halfDuplexText1,"Half Duplex Text 1");
sl@0
  2507
				TBuf8<19> halfDuplexBuf_8;
sl@0
  2508
				halfDuplexBuf_8.Copy(halfDuplexText1);
sl@0
  2509
				iTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf_8);
sl@0
  2510
				if(iTfer == NULL)
sl@0
  2511
					{
sl@0
  2512
					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iTfer=NULL\n"));
sl@0
  2513
					r = KErrNoMemory;
sl@0
  2514
					}
sl@0
  2515
				else
sl@0
  2516
					{
sl@0
  2517
					_LIT(halfDuplexText2,"Half Duplex Text 2");
sl@0
  2518
					TBuf8<19> halfDuplexBuf2_8;
sl@0
  2519
					halfDuplexBuf2_8.Copy(halfDuplexText2);
sl@0
  2520
					TIicBusTransfer* tempHdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, &halfDuplexBuf2_8);
sl@0
  2521
					if(tempHdTfer == NULL)
sl@0
  2522
						{
sl@0
  2523
						CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempHdTfer=NULL\n"));
sl@0
  2524
						r = KErrNoMemory;
sl@0
  2525
						}
sl@0
  2526
					else
sl@0
  2527
						{
sl@0
  2528
						iTfer->LinkAfter(tempHdTfer);
sl@0
  2529
						}
sl@0
  2530
					}
sl@0
  2531
				if(r == KErrNone)
sl@0
  2532
					{
sl@0
  2533
					_LIT(fullDuplexText1,"Full Duplex Text 1");
sl@0
  2534
					TBuf8<19> fullDuplexBuf1_8;
sl@0
  2535
					fullDuplexBuf1_8.Copy(fullDuplexText1);
sl@0
  2536
					iFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf1_8);
sl@0
  2537
					if(iFdTfer == NULL)
sl@0
  2538
						{
sl@0
  2539
						CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - iFdTfer=NULL\n"));
sl@0
  2540
						r = KErrNoMemory;
sl@0
  2541
						}
sl@0
  2542
					else
sl@0
  2543
						{
sl@0
  2544
						_LIT(fullDuplexText2,"Full Duplex Text 2");
sl@0
  2545
						TBuf8<19> fullDuplexBuf2_8;
sl@0
  2546
						fullDuplexBuf2_8.Copy(fullDuplexText2);
sl@0
  2547
						TIicBusTransfer* tempFdTfer = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, &fullDuplexBuf2_8);
sl@0
  2548
						if(tempFdTfer == NULL)
sl@0
  2549
							{
sl@0
  2550
							CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - tempFdTfer=NULL\n"));
sl@0
  2551
							r = KErrNoMemory;
sl@0
  2552
							}
sl@0
  2553
						else
sl@0
  2554
							{
sl@0
  2555
							iFdTfer->LinkAfter(tempFdTfer);
sl@0
  2556
							}
sl@0
  2557
						}
sl@0
  2558
					}
sl@0
  2559
				}
sl@0
  2560
sl@0
  2561
			// Add the Header and Transfers to the Transaction
sl@0
  2562
			if(r == KErrNone)
sl@0
  2563
				r = iTrans->SetHalfDuplexTrans(iSpiBuf, iTfer);
sl@0
  2564
				if(r != KErrNone)
sl@0
  2565
					{
sl@0
  2566
					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetHalfDuplexTrans returned %d\n",r));
sl@0
  2567
					}
sl@0
  2568
sl@0
  2569
			if(r == KErrNone)
sl@0
  2570
				r = iTrans->SetFullDuplexTrans(iFdTfer);
sl@0
  2571
				if(r != KErrNone)
sl@0
  2572
					{
sl@0
  2573
					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - SetFullDuplexTrans returned %d\n",r));
sl@0
  2574
					}
sl@0
  2575
sl@0
  2576
			// Specify the callback object to use
sl@0
  2577
			if(r == KErrNone)
sl@0
  2578
				{
sl@0
  2579
				cb = new TIicBusCallback(TransModifCallback, this, iDfcQue, 5); // 5 arbitrary
sl@0
  2580
				if(cb == NULL)
sl@0
  2581
					{
sl@0
  2582
					CLIENT_PRINT(("DChannelIicClient::DoRequest ECtrlIoTestBufReUse ERROR - cb=NULL\n"));
sl@0
  2583
					r = KErrNoMemory;
sl@0
  2584
					}
sl@0
  2585
				}
sl@0
  2586
sl@0
  2587
			// Since the transaction is not yet queued, should be able to modify the transfer and transaction content
sl@0
  2588
			TestTransModification(iTrans, iTfer, iFdTfer, iSpiBuf);
sl@0
  2589
sl@0
  2590
			// Store the relevant data in this object's iTransBufReuseData member
sl@0
  2591
			iTransBufReuseData.iTransaction = iTrans;
sl@0
  2592
			iTransBufReuseData.iHdTfer = iTfer;
sl@0
  2593
			iTransBufReuseData.iFdTfer = iFdTfer;
sl@0
  2594
			iTransBufReuseData.iHdr = iSpiBuf;
sl@0
  2595
			iTransBufReuseData.iCallback = cb;
sl@0
  2596
sl@0
  2597
			// Now queue the transaction. The callback function will re-apply the modification tests and delete the
sl@0
  2598
			// objects created here
sl@0
  2599
			// If the queueing fails, complete the test here and clean up
sl@0
  2600
			r = QueueTransaction((TInt)a1, iTrans, cb);
sl@0
  2601
			if(r != KErrNone)
sl@0
  2602
				{
sl@0
  2603
				Kern::RequestComplete(iClient, iStatus, r);
sl@0
  2604
				delete iTransBufReuseData.iCallback;	// Must do this before deleting the Transaction in CleanupTransaction
sl@0
  2605
				CleanupTransaction(iTrans);
sl@0
  2606
				}
sl@0
  2607
			break;
sl@0
  2608
			}
sl@0
  2609
		default:
sl@0
  2610
			{
sl@0
  2611
			CLIENT_PRINT(("DChannelIicClient::DoRequest - unrecognised value for aId=0x%x\n",aId));
sl@0
  2612
			r=KErrArgument;
sl@0
  2613
			break;
sl@0
  2614
			}
sl@0
  2615
		}
sl@0
  2616
	return r;
sl@0
  2617
	}
sl@0
  2618
sl@0
  2619
sl@0
  2620
// Support for MasterSlave processing
sl@0
  2621
static void MsSlaveClientCallbackFunc(TInt aChannelId, TInt aReturn, TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny*	aParam)
sl@0
  2622
	{
sl@0
  2623
	CLIENT_PRINT(("> MsSlaveClientCallbackFunc() - aChannelId=0x%x,aReturn=%d,aTrigger=0x%x,aRxWords=0x%x,aTxWords=0x%x,aParam=0x%x\n",aChannelId,aReturn,aTrigger,aRxWords,aTxWords,aParam));
sl@0
  2624
	(void)aTxWords; // Unused if CLIENT_PRINT is disabled
sl@0
  2625
	(void)aRxWords; // Unused if CLIENT_PRINT is disabled
sl@0
  2626
	DChannelIicClient* channel = (DChannelIicClient*)aParam;
sl@0
  2627
	CLIENT_PRINT(("MsSlaveClientCallbackFunc() - channel=0x%x\n",channel));
sl@0
  2628
	if(aTrigger == EAsyncCaptChan)
sl@0
  2629
		{
sl@0
  2630
		CLIENT_PRINT(("MsSlaveClientCallbackFunc: capture channel completed\n"));
sl@0
  2631
		// Set iChannelId, and write to user-side variable.
sl@0
  2632
		channel->iChannelId=aChannelId;
sl@0
  2633
		TInt r=Kern::ThreadRawWrite(channel->iClient,channel->iClientChanId,&aChannelId,sizeof(TInt));
sl@0
  2634
		if(r == KErrNone)
sl@0
  2635
			r=aReturn;
sl@0
  2636
	    channel->RequestComplete(r);	// Inform user of error
sl@0
  2637
		return;
sl@0
  2638
		}
sl@0
  2639
	else
sl@0
  2640
		{
sl@0
  2641
		CLIENT_PRINT(("\nMsSlaveClientCallbackFunc: trigger condition 0x%x is not recognised \n\n",aTrigger));
sl@0
  2642
		channel->RequestComplete(aReturn);	// Inform user of error
sl@0
  2643
		}
sl@0
  2644
	}
sl@0
  2645
sl@0
  2646
void DChannelIicClient::RequestComplete(TInt r)
sl@0
  2647
	{
sl@0
  2648
	Kern::RequestComplete(iClient, iStatus, r);
sl@0
  2649
	}
sl@0
  2650
sl@0
  2651
sl@0
  2652
TInt DChannelIicClient::InitSlaveClient()
sl@0
  2653
	{
sl@0
  2654
	iNotif = new TIicBusSlaveCallback(MsSlaveClientCallbackFunc, (TAny*)this, iDfcQue, KIicSlaveClientDfcPriority);
sl@0
  2655
	if(iNotif == NULL)
sl@0
  2656
		{
sl@0
  2657
		CLIENT_PRINT(("> DChannelIicClient::InitSlaveClient ERROR unable to allocate space TIicBusSlaveCallback* iNotif \n"));
sl@0
  2658
		return KErrNoMemory;
sl@0
  2659
		}
sl@0
  2660
	return KErrNone;
sl@0
  2661
	}
sl@0
  2662