os/kernelhwsrv/kernel/eka/drivers/iic/iic.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
// e32\drivers\iic.cpp
sl@0
    15
// IIC Controller and public API Implementation
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <drivers/iic.h>
sl@0
    19
#include <drivers/iic_channel.h>
sl@0
    20
#include "iic_priv.h"
sl@0
    21
sl@0
    22
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    23
#include <drivers/iic_trace.h>
sl@0
    24
#endif
sl@0
    25
sl@0
    26
// Global Controller pointer
sl@0
    27
static DIicBusController* TheController = NULL;
sl@0
    28
sl@0
    29
//
sl@0
    30
//		Implementation of generic IicBus API for client interface
sl@0
    31
//
sl@0
    32
EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
sl@0
    33
	{
sl@0
    34
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    35
	IIC_MQTRANSSYNC_START_PIL_TRACE;
sl@0
    36
#endif
sl@0
    37
	TInt r=TheController->QueueTransaction(aBusId, aTransaction);
sl@0
    38
sl@0
    39
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    40
	IIC_MQTRANSSYNC_END_PIL_TRACE;
sl@0
    41
#endif
sl@0
    42
	return r;
sl@0
    43
	}
sl@0
    44
sl@0
    45
EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
sl@0
    46
	{
sl@0
    47
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    48
	IIC_MQTRANSASYNC_START_PIL_TRACE;
sl@0
    49
#endif
sl@0
    50
	TInt r=TheController->QueueTransaction(aBusId, aTransaction, aCallback);
sl@0
    51
sl@0
    52
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    53
	IIC_MQTRANSASYNC_END_PIL_TRACE;
sl@0
    54
#endif
sl@0
    55
	return r;
sl@0
    56
	}
sl@0
    57
sl@0
    58
EXPORT_C TInt IicBus::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
sl@0
    59
	{
sl@0
    60
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    61
	IIC_MCANCELTRANS_START_PIL_TRACE;
sl@0
    62
#endif
sl@0
    63
	TInt r=TheController->CancelTransaction(aBusId, aTransaction);
sl@0
    64
sl@0
    65
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    66
	IIC_MCANCELTRANS_END_PIL_TRACE;
sl@0
    67
#endif
sl@0
    68
	return r;
sl@0
    69
	}
sl@0
    70
sl@0
    71
EXPORT_C TInt IicBus::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
sl@0
    72
	{
sl@0
    73
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    74
	if(!aAsynch)
sl@0
    75
		{
sl@0
    76
		IIC_SCAPTCHANSYNC_START_PIL_TRACE;
sl@0
    77
		}
sl@0
    78
	else
sl@0
    79
		{
sl@0
    80
		IIC_SCAPTCHANASYNC_START_PIL_TRACE;
sl@0
    81
		}
sl@0
    82
#endif
sl@0
    83
	TInt r=TheController->CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
sl@0
    84
sl@0
    85
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    86
	if(!aAsynch)
sl@0
    87
		{
sl@0
    88
		IIC_SCAPTCHANSYNC_END_PIL_TRACE;
sl@0
    89
		}
sl@0
    90
#endif
sl@0
    91
	return r;
sl@0
    92
	}
sl@0
    93
sl@0
    94
EXPORT_C TInt IicBus::ReleaseChannel(TInt aChannelId)
sl@0
    95
	{
sl@0
    96
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
    97
	IIC_SRELCHAN_START_PIL_TRACE;
sl@0
    98
#endif
sl@0
    99
	TInt r=TheController->ReleaseChannel(aChannelId);
sl@0
   100
sl@0
   101
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   102
	IIC_SRELCHAN_END_PIL_TRACE;
sl@0
   103
#endif
sl@0
   104
	return r;
sl@0
   105
	}
sl@0
   106
sl@0
   107
EXPORT_C TInt IicBus::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
sl@0
   108
	{
sl@0
   109
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   110
	IIC_SREGRXBUF_START_PIL_TRACE;
sl@0
   111
#endif
sl@0
   112
	TInt r=TheController->RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
sl@0
   113
sl@0
   114
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   115
	IIC_SREGRXBUF_END_PIL_TRACE;
sl@0
   116
#endif
sl@0
   117
	return r;
sl@0
   118
	}
sl@0
   119
sl@0
   120
EXPORT_C TInt IicBus::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
sl@0
   121
	{
sl@0
   122
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   123
	IIC_SREGTXBUF_START_PIL_TRACE;
sl@0
   124
#endif
sl@0
   125
	TInt r=TheController->RegisterTxBuffer(aChannelId, aTxBuffer, aBufGranularity, aNumWords, aOffset);
sl@0
   126
sl@0
   127
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   128
	IIC_SREGTXBUF_END_PIL_TRACE;
sl@0
   129
#endif
sl@0
   130
	return r;
sl@0
   131
	}
sl@0
   132
sl@0
   133
EXPORT_C TInt IicBus::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
sl@0
   134
	{
sl@0
   135
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   136
	IIC_SNOTIFTRIG_START_PIL_TRACE;
sl@0
   137
#endif
sl@0
   138
	TInt r=TheController->SetNotificationTrigger(aChannelId, aTrigger);
sl@0
   139
sl@0
   140
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   141
	IIC_SNOTIFTRIG_END_PIL_TRACE;
sl@0
   142
#endif
sl@0
   143
	return r;
sl@0
   144
	}
sl@0
   145
sl@0
   146
EXPORT_C TInt IicBus::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
sl@0
   147
	{
sl@0
   148
	return(TheController->StaticExtension(aId, aFunction, aParam1, aParam2));
sl@0
   149
	}
sl@0
   150
sl@0
   151
sl@0
   152
//
sl@0
   153
//		Bus Controller
sl@0
   154
//
sl@0
   155
sl@0
   156
//  auxiliary function for ordering entries in the array of channels
sl@0
   157
TInt DIicBusController::OrderEntries(const DIicBusChannel& aMatch, const DIicBusChannel& aEntry)
sl@0
   158
	{
sl@0
   159
	TUint8 l=(TUint8)aMatch.ChannelNumber();
sl@0
   160
	TUint8 r=(TUint8)aEntry.ChannelNumber();
sl@0
   161
	if(l>r)
sl@0
   162
		return -1;
sl@0
   163
	else if(l<r)
sl@0
   164
		return 1;
sl@0
   165
	else
sl@0
   166
		return 0;
sl@0
   167
	}
sl@0
   168
sl@0
   169
// global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
sl@0
   170
TLinearOrder<DIicBusChannel> EntryOrder(DIicBusController::OrderEntries);
sl@0
   171
sl@0
   172
// Implementation for DIicBusController
sl@0
   173
//
sl@0
   174
sl@0
   175
TInt DIicBusController::Create()
sl@0
   176
	{
sl@0
   177
	TInt r=KErrNone;
sl@0
   178
	iChanLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2);  // Semi-arbitrary, low priority value
sl@0
   179
	iCaptLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2);  // Semi-arbitrary, low priority value
sl@0
   180
	if((iChanLock == NULL)||(iCaptLock == NULL))
sl@0
   181
		{
sl@0
   182
		delete iChanLock;
sl@0
   183
		delete iCaptLock;
sl@0
   184
		r=KErrNoMemory;
sl@0
   185
		}
sl@0
   186
	return r;
sl@0
   187
	}
sl@0
   188
sl@0
   189
DIicBusController::~DIicBusController()
sl@0
   190
	{
sl@0
   191
#ifdef IIC_SIMULATED_PSL
sl@0
   192
	for(TInt i=0; i<iChannelArray.Count(); i++)
sl@0
   193
		{
sl@0
   194
		DIicBusChannel* ptr=iChannelArray[i];
sl@0
   195
		// Remove the channel from the array
sl@0
   196
		iChannelArray.Remove(i);
sl@0
   197
		// Delete the channel object
sl@0
   198
		delete ptr;
sl@0
   199
		};
sl@0
   200
sl@0
   201
	iChannelArray.Reset();
sl@0
   202
	delete iChanLock;
sl@0
   203
	delete iCaptLock;
sl@0
   204
#endif
sl@0
   205
	}
sl@0
   206
sl@0
   207
TInt DIicBusController::GetChanWriteAccess()
sl@0
   208
	{
sl@0
   209
	// Can only have one insertion or removal active at any one time
sl@0
   210
	// Can not perform an insertion or removal while a read is in progress
sl@0
   211
	// If either of the two above conditions exist, return KErrInUse
sl@0
   212
	// Otherwise, set the flag to indicate that a write is in progress
sl@0
   213
	// and return KErrNone.
sl@0
   214
	TInt chanIntState=0;
sl@0
   215
	chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
sl@0
   216
	if(iChanRwFlags != 0)
sl@0
   217
		{
sl@0
   218
		__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   219
		return KErrInUse;
sl@0
   220
		}
sl@0
   221
	iChanRwFlags |= EWriteInProgress;
sl@0
   222
	__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   223
	return KErrNone;
sl@0
   224
	}
sl@0
   225
sl@0
   226
void DIicBusController::FreeChanWriteAccess()
sl@0
   227
	{
sl@0
   228
	// If an insertion or removal is in progress, no other modifying operation
sl@0
   229
	// can be active. Reads are also not permitted - so iChanRwFlags can only be
sl@0
   230
	// EWriteInProgress.
sl@0
   231
	__ASSERT_DEBUG(iChanRwFlags == EWriteInProgress, Kern::Fault(KIicPanic,__LINE__));
sl@0
   232
	TInt chanIntState=0;
sl@0
   233
 	chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
sl@0
   234
 	iChanRwFlags &= ~EWriteInProgress;
sl@0
   235
 	__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   236
	}
sl@0
   237
sl@0
   238
TInt DIicBusController::GetChanReadAccess()
sl@0
   239
	{
sl@0
   240
	// No reads are permitted while an insertion or removal is in progress
sl@0
   241
	// If one of the above operations is in progress return KErrInUse
sl@0
   242
	// Can have several concurrent reads at any one time - so increment
sl@0
   243
	// the count of such operations as well as ensuring the flag is set to indicate
sl@0
   244
	// a read is in progress
sl@0
   245
	TInt chanIntState=0;
sl@0
   246
	chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
sl@0
   247
	if(iChanRwFlags == EWriteInProgress)
sl@0
   248
		{
sl@0
   249
		__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   250
		return KErrInUse;
sl@0
   251
		}
sl@0
   252
	__ASSERT_DEBUG(iChanRdCount!=0xFFFFFFFF, Kern::Fault(KIicPanic,__LINE__)); // Overflow
sl@0
   253
	iChanRdCount++;
sl@0
   254
	iChanRwFlags |= EReadInProgress;
sl@0
   255
	__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   256
	return KErrNone;
sl@0
   257
	}
sl@0
   258
sl@0
   259
void DIicBusController::FreeChanReadAccess()
sl@0
   260
	{
sl@0
   261
	// No insertions or removals are permitted while a read is in progress
sl@0
   262
	// so iChanRwFlags can only be EReadInProgress
sl@0
   263
	// Multiple reads can be in progress concurrently, so the count must be decremented
sl@0
   264
	TInt chanIntState=0;
sl@0
   265
	chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
sl@0
   266
	__ASSERT_DEBUG(iChanRwFlags == EReadInProgress, Kern::Fault(KIicPanic,__LINE__));
sl@0
   267
	__ASSERT_DEBUG(iChanRdCount>0, Kern::Fault(KIicPanic,__LINE__));
sl@0
   268
	iChanRdCount--;
sl@0
   269
	if(iChanRdCount == 0)
sl@0
   270
		iChanRwFlags &= ~EReadInProgress;
sl@0
   271
	__SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
sl@0
   272
	}
sl@0
   273
sl@0
   274
TInt DIicBusController::RequestTypeSupported(const TInt aBusId, DIicBusChannelMaster* const aChannel)
sl@0
   275
	{
sl@0
   276
	TInt32 reqBusType;
sl@0
   277
	reqBusType = GET_BUS_TYPE(aBusId);
sl@0
   278
	__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RequestTypeSupported, BusType=0x%x\n", reqBusType));
sl@0
   279
sl@0
   280
	if(reqBusType != aChannel->BusType())
sl@0
   281
		{
sl@0
   282
		return KErrNotSupported;
sl@0
   283
		}
sl@0
   284
sl@0
   285
	return KErrNone;
sl@0
   286
	}
sl@0
   287
sl@0
   288
sl@0
   289
EXPORT_C TInt DIicBusController::RegisterChannels(DIicBusChannel** aListChannels, TInt aNumberChannels)
sl@0
   290
	{
sl@0
   291
// To be used by Channel implementations to register a list of supported channels
sl@0
   292
    __KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::RegisterChannels, aListChannels=0x%x, aNumberChannels=%d\n",aListChannels,aNumberChannels));
sl@0
   293
	__ASSERT_DEBUG(aListChannels!=NULL, Kern::Fault(KIicPanic,__LINE__));
sl@0
   294
sl@0
   295
	RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
sl@0
   296
sl@0
   297
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   298
	IIC_REGISTERCHANS_START_PIL_TRACE;
sl@0
   299
#endif
sl@0
   300
	// Get access to the channel pointer array - exit if it is currently being modfied
sl@0
   301
	TInt r=KErrNone;
sl@0
   302
	if((r=TheController->GetChanWriteAccess()) == KErrNone)
sl@0
   303
		{
sl@0
   304
#ifdef _DEBUG
sl@0
   305
		__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On entry, iChannelArray ...\n"));
sl@0
   306
		TheController->DumpChannelArray();
sl@0
   307
#endif
sl@0
   308
		// Loop for aNumberChannels	and write directly to the channel array
sl@0
   309
		DIicBusChannel** chanIterator = aListChannels;
sl@0
   310
		for(TInt iteration = 0; iteration < aNumberChannels; ++iteration, ++chanIterator)
sl@0
   311
			{
sl@0
   312
			DIicBusChannel* chanPtr = *chanIterator;
sl@0
   313
			__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - adding channel number %d\n",chanPtr->ChannelNumber()));
sl@0
   314
			TInt r = chanArray->InsertInOrder(chanPtr,EntryOrder);
sl@0
   315
			if(r!=KErrNone)
sl@0
   316
				break;
sl@0
   317
			}
sl@0
   318
sl@0
   319
#ifdef _DEBUG
sl@0
   320
		 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On exit, iChannelArray ...\n"));
sl@0
   321
		TheController->DumpChannelArray();
sl@0
   322
#endif
sl@0
   323
		TheController->FreeChanWriteAccess();
sl@0
   324
		}
sl@0
   325
	else
sl@0
   326
		{
sl@0
   327
		__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanWriteAccess returned %d\n",r));
sl@0
   328
		}
sl@0
   329
sl@0
   330
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   331
	IIC_REGISTERCHANS_END_PIL_TRACE;
sl@0
   332
#endif
sl@0
   333
	return r;
sl@0
   334
	}
sl@0
   335
sl@0
   336
sl@0
   337
EXPORT_C TInt DIicBusController::DeRegisterChannel(DIicBusChannel* aChannel)
sl@0
   338
	{
sl@0
   339
// To be used by Channel implementations to deregister a channel
sl@0
   340
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel, aChannel=0x%x\n",aChannel));
sl@0
   341
	if(aChannel == NULL)
sl@0
   342
		return KErrArgument;
sl@0
   343
sl@0
   344
	RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
sl@0
   345
sl@0
   346
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   347
	IIC_DEREGISTERCHAN_START_PIL_TRACE;
sl@0
   348
#endif
sl@0
   349
	TInt r=KErrNone;
sl@0
   350
	// Get access to the channel pointer array - exit if it is currently unavailable
sl@0
   351
	// Gaining write access will prevent a client of a Master Channel from instigating a new QueueTransaction
sl@0
   352
	// (or CancelTransaction), and it will obstruct a client of a Slave Channel in CaptureChannel.
sl@0
   353
	if((r=TheController->GetChanWriteAccess())!=KErrNone)
sl@0
   354
		return r;
sl@0
   355
sl@0
   356
	// Check channel is registered
sl@0
   357
	TInt chanIndex = chanArray->FindInOrder(aChannel,EntryOrder);
sl@0
   358
	if(chanIndex<0)
sl@0
   359
		{
sl@0
   360
		TheController->FreeChanWriteAccess();
sl@0
   361
		return KErrNotFound;
sl@0
   362
		}
sl@0
   363
sl@0
   364
#ifdef _DEBUG
sl@0
   365
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On entry, iChannelArray ...\n"));
sl@0
   366
	TheController->DumpChannelArray();
sl@0
   367
#endif
sl@0
   368
sl@0
   369
	// Remove the channel from the array
sl@0
   370
	// Note that this does not delete the channel object
sl@0
   371
	chanArray->Remove(chanIndex);
sl@0
   372
sl@0
   373
#ifdef _DEBUG
sl@0
   374
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On exit, iChannelArray ...\n"));
sl@0
   375
	TheController->DumpChannelArray();
sl@0
   376
#endif
sl@0
   377
	TheController->FreeChanWriteAccess();
sl@0
   378
sl@0
   379
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   380
	IIC_DEREGISTERCHAN_END_PIL_TRACE;
sl@0
   381
#endif
sl@0
   382
	return KErrNone;
sl@0
   383
	}
sl@0
   384
sl@0
   385
TInt DIicBusController::FindCapturedChanById(TCapturedChannel aCapturedChan, TInt& aIndex)
sl@0
   386
	{
sl@0
   387
	TInt index=0;
sl@0
   388
	TInt r=KErrNotFound;
sl@0
   389
	do
sl@0
   390
		{
sl@0
   391
		if(iCapturedChannels[index].iChannelId == aCapturedChan.iChannelId)
sl@0
   392
			{
sl@0
   393
			aIndex=index;
sl@0
   394
			r=KErrNone;
sl@0
   395
			}
sl@0
   396
		index++;
sl@0
   397
		} while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
sl@0
   398
	return r;
sl@0
   399
	}
sl@0
   400
sl@0
   401
TInt DIicBusController::FindCapturedChan(TCapturedChannel aCapturedChan, TInt& aIndex)
sl@0
   402
	{
sl@0
   403
	TInt index=0;
sl@0
   404
	TInt r=KErrNotFound;
sl@0
   405
	do
sl@0
   406
		{
sl@0
   407
		if(iCapturedChannels[index] == aCapturedChan)
sl@0
   408
			{
sl@0
   409
			aIndex=index;
sl@0
   410
			r=KErrNone;
sl@0
   411
			}
sl@0
   412
		index++;
sl@0
   413
		} while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
sl@0
   414
	return r;
sl@0
   415
	}
sl@0
   416
sl@0
   417
TInt DIicBusController::InsertCaptChanInArray(TCapturedChannel aCapturedChan)
sl@0
   418
	{
sl@0
   419
	__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InsertCaptChanInArray \n"));
sl@0
   420
	// Ensure the channel hasn't already been inserted in the array
sl@0
   421
	// If found, fault the Kernel
sl@0
   422
	TInt dumInt = 0;
sl@0
   423
	TInt r=FindCapturedChan(aCapturedChan,dumInt);
sl@0
   424
	__ASSERT_DEBUG(r!=KErrNone, Kern::Fault(KIicPanic,__LINE__));
sl@0
   425
sl@0
   426
	// Loop the array and insert in the first available slot
sl@0
   427
	// If no slots are available return KErrNotReady
sl@0
   428
	TInt index=0;
sl@0
   429
	TCapturedChannel emptyChan;
sl@0
   430
	for(;index<KMaxNumCapturedChannels;++index)
sl@0
   431
		{
sl@0
   432
		if(iCapturedChannels[index] == emptyChan)
sl@0
   433
			{
sl@0
   434
			// Found a space
sl@0
   435
			iCapturedChannels[index]=aCapturedChan;
sl@0
   436
			break;
sl@0
   437
			}
sl@0
   438
		}
sl@0
   439
	if(index>=KMaxNumCapturedChannels)
sl@0
   440
		r = KErrNotReady;
sl@0
   441
	return r;
sl@0
   442
	}
sl@0
   443
sl@0
   444
TInt DIicBusController::RemoveCaptChanFromArray(TCapturedChannel aCapturedChan)
sl@0
   445
	{
sl@0
   446
	// Remove the entry from the array
sl@0
   447
	// If the entry is not present return KErrArgument
sl@0
   448
	TInt index=-1;
sl@0
   449
	TInt r=FindCapturedChan(aCapturedChan,index);
sl@0
   450
	if((r!=KErrNone)||(index>=KMaxNumCapturedChannels))
sl@0
   451
		return KErrArgument;
sl@0
   452
	iCapturedChannels[index].iChanPtr=NULL;
sl@0
   453
	iCapturedChannels[index].iChannelId=0;
sl@0
   454
	return KErrNone;
sl@0
   455
	}
sl@0
   456
sl@0
   457
sl@0
   458
TInt DIicBusController::InstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
sl@0
   459
	{
sl@0
   460
#ifdef _DEBUG
sl@0
   461
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On entry, iCapturedChannels ...\n"));
sl@0
   462
	DumpCapturedChannels();
sl@0
   463
#endif
sl@0
   464
	TInt r=KErrNone;
sl@0
   465
	TCapturedChannel capturedChan((TInt)aChannelId,(DIicBusChannelSlave*)aChanPtr);
sl@0
   466
	// Because insertions are bounded by the size of the array and do not involve allocating
sl@0
   467
	// or freeing memory, simply take the spinlock at the start of the operation and release at the end
sl@0
   468
	TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
sl@0
   469
	r=InsertCaptChanInArray(capturedChan);
sl@0
   470
	__SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
sl@0
   471
	if(r!=KErrNone)
sl@0
   472
		return r;
sl@0
   473
sl@0
   474
#ifdef _DEBUG
sl@0
   475
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On exit, iCapturedChannels ...\n"));
sl@0
   476
	DumpCapturedChannels();
sl@0
   477
#endif
sl@0
   478
	return KErrNone;
sl@0
   479
	}
sl@0
   480
sl@0
   481
TInt DIicBusController::DeInstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
sl@0
   482
	{
sl@0
   483
#ifdef _DEBUG
sl@0
   484
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On entry, iCapturedChannels ...\n"));
sl@0
   485
	DumpCapturedChannels();
sl@0
   486
#endif
sl@0
   487
	TInt r = KErrNone;
sl@0
   488
	TCapturedChannel capturedChan((TInt) aChannelId, (DIicBusChannelSlave*) aChanPtr);
sl@0
   489
	// Because removals are bounded by the size of the array and do not involve allocating
sl@0
   490
	// or freeing memory, simply take the spinlock at the start of the operation and release at the end
sl@0
   491
	TInt captIntState = __SPIN_LOCK_IRQSAVE(*iCaptLock);
sl@0
   492
	r = RemoveCaptChanFromArray(capturedChan);
sl@0
   493
	__SPIN_UNLOCK_IRQRESTORE(*iCaptLock, captIntState);
sl@0
   494
	if(r != KErrNone)
sl@0
   495
		return r;
sl@0
   496
sl@0
   497
#ifdef _DEBUG
sl@0
   498
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On exit, iCapturedChannels ...\n"));
sl@0
   499
	DumpCapturedChannels();
sl@0
   500
#endif
sl@0
   501
	return KErrNone;
sl@0
   502
	}
sl@0
   503
sl@0
   504
	// Master-side API
sl@0
   505
TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
sl@0
   506
	{
sl@0
   507
	__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
sl@0
   508
	if(!aTransaction)
sl@0
   509
		{
sl@0
   510
		return KErrArgument;
sl@0
   511
		}
sl@0
   512
sl@0
   513
	// Get a pointer to the channel
sl@0
   514
	TInt dumInt = 0;
sl@0
   515
	DIicBusChannel* chanPtr = NULL;
sl@0
   516
	// Can only read the channel array if it is not currently being modified
sl@0
   517
	TInt r = GetChanReadAccess();
sl@0
   518
	if(r != KErrNone)
sl@0
   519
		{
sl@0
   520
		return r;
sl@0
   521
		}
sl@0
   522
	r = GetChanPtr(aBusId, dumInt, chanPtr);
sl@0
   523
	if(r == KErrNone)
sl@0
   524
		{
sl@0
   525
		if(!chanPtr)
sl@0
   526
			{
sl@0
   527
			r = KErrArgument;
sl@0
   528
			}
sl@0
   529
		else
sl@0
   530
			{
sl@0
   531
			switch(chanPtr->ChannelType())
sl@0
   532
				{
sl@0
   533
				// QueueTransaction requests are only supported by channels in Master mode.
sl@0
   534
				case DIicBusChannel::ESlave:
sl@0
   535
					{
sl@0
   536
					r = KErrNotSupported;
sl@0
   537
					break;
sl@0
   538
					}
sl@0
   539
				// If the request is supported by the Master channel, send it to the channel for processing in its thread
sl@0
   540
				case DIicBusChannel::EMasterSlave:
sl@0
   541
					{
sl@0
   542
					r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
sl@0
   543
					if(r == KErrNone)
sl@0
   544
						{
sl@0
   545
						aTransaction->iBusId = aBusId;
sl@0
   546
						r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction));
sl@0
   547
						}
sl@0
   548
					break;
sl@0
   549
					}
sl@0
   550
				case DIicBusChannel::EMaster:
sl@0
   551
					{
sl@0
   552
					r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
sl@0
   553
					if(r == KErrNone)
sl@0
   554
						{
sl@0
   555
						aTransaction->iBusId = aBusId;
sl@0
   556
						r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction));
sl@0
   557
						}
sl@0
   558
					break;
sl@0
   559
					}
sl@0
   560
				default:
sl@0
   561
					{
sl@0
   562
					r = KErrGeneral;
sl@0
   563
					}
sl@0
   564
				}
sl@0
   565
			}
sl@0
   566
		}
sl@0
   567
	FreeChanReadAccess();
sl@0
   568
	return r;
sl@0
   569
	}
sl@0
   570
sl@0
   571
TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
sl@0
   572
	{
sl@0
   573
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x,aCallback=0x%x\n",aBusId,aTransaction,aCallback));
sl@0
   574
	if(!aTransaction || !aCallback)
sl@0
   575
		{
sl@0
   576
		return KErrArgument;
sl@0
   577
		}
sl@0
   578
sl@0
   579
	// Get a pointer to the channel
sl@0
   580
	TInt dumInt = 0;
sl@0
   581
	DIicBusChannel* chanPtr = NULL;
sl@0
   582
	// Can only read the channel array if it is not currently being modified
sl@0
   583
	TInt r = GetChanReadAccess();
sl@0
   584
	if(r == KErrNone)
sl@0
   585
		{
sl@0
   586
		r = GetChanPtr(aBusId, dumInt, chanPtr);
sl@0
   587
		if(r == KErrNone)
sl@0
   588
			{
sl@0
   589
			if(!chanPtr)
sl@0
   590
				{
sl@0
   591
				r = KErrArgument;
sl@0
   592
				}
sl@0
   593
			else
sl@0
   594
				{
sl@0
   595
				switch(chanPtr->ChannelType())
sl@0
   596
					{
sl@0
   597
					// QueueTransaction requests are only supported by channels in Master mode.
sl@0
   598
					case DIicBusChannel::ESlave:
sl@0
   599
						{
sl@0
   600
						r = KErrNotSupported;
sl@0
   601
						break;
sl@0
   602
						}
sl@0
   603
					// If the request is supported by the Master channel, send it to the channel for processing in its thread
sl@0
   604
					case DIicBusChannel::EMasterSlave:
sl@0
   605
						{
sl@0
   606
						r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
sl@0
   607
						if(r == KErrNone)
sl@0
   608
							{
sl@0
   609
							aTransaction->iBusId = aBusId;
sl@0
   610
							r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction, aCallback));
sl@0
   611
							}
sl@0
   612
						break;
sl@0
   613
						}
sl@0
   614
					case DIicBusChannel::EMaster:
sl@0
   615
						{
sl@0
   616
						r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
sl@0
   617
						if(r == KErrNone)
sl@0
   618
							{
sl@0
   619
							aTransaction->iBusId = aBusId;
sl@0
   620
							r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction, aCallback));
sl@0
   621
							}
sl@0
   622
						break;
sl@0
   623
						}
sl@0
   624
					default:
sl@0
   625
						{
sl@0
   626
						r = KErrGeneral;
sl@0
   627
						}
sl@0
   628
					}
sl@0
   629
				}
sl@0
   630
			}
sl@0
   631
		}
sl@0
   632
	FreeChanReadAccess();
sl@0
   633
	return r;
sl@0
   634
	}
sl@0
   635
sl@0
   636
sl@0
   637
TInt DIicBusController::GetChanPtr(const TInt aBusId, TInt &aIndex, DIicBusChannel*& aChan)
sl@0
   638
	{
sl@0
   639
    __KTRACE_OPT(KIIC, 	Kern::Printf("DIicBusController::GetChanPtr, aBusId=0x%x\n",aBusId));
sl@0
   640
sl@0
   641
	TInt32 chanId;
sl@0
   642
	chanId = GET_CHAN_NUM(aBusId);
sl@0
   643
sl@0
   644
	__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanId=0x%x\n", chanId));
sl@0
   645
	DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
sl@0
   646
	searchChannel.SetChannelNumber((TInt8)chanId);
sl@0
   647
sl@0
   648
	TInt r = KErrNotFound;
sl@0
   649
	aIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
sl@0
   650
	if(aIndex >= 0)
sl@0
   651
		{
sl@0
   652
		aChan = iChannelArray[aIndex];
sl@0
   653
		r = KErrNone;
sl@0
   654
		}
sl@0
   655
sl@0
   656
	__KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanPtr=0x%x, index=%d\n", aChan, aIndex));
sl@0
   657
	return r;
sl@0
   658
	}
sl@0
   659
sl@0
   660
sl@0
   661
TInt DIicBusController::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
sl@0
   662
	{
sl@0
   663
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
sl@0
   664
	if(!aTransaction)
sl@0
   665
		{
sl@0
   666
		return KErrArgument;
sl@0
   667
		}
sl@0
   668
sl@0
   669
	// Get the channel
sl@0
   670
	TInt dumInt = 0;
sl@0
   671
	DIicBusChannel* chanPtr = NULL;
sl@0
   672
sl@0
   673
	// Can only read the channel array if it is not currently being modified
sl@0
   674
	TInt r = GetChanReadAccess();
sl@0
   675
	if(r == KErrNone)
sl@0
   676
		{
sl@0
   677
		r = GetChanPtr(aBusId, dumInt, chanPtr);
sl@0
   678
		if(r == KErrNone)
sl@0
   679
			{
sl@0
   680
			if(!chanPtr)
sl@0
   681
				{
sl@0
   682
				r = KErrArgument;
sl@0
   683
				}
sl@0
   684
			else
sl@0
   685
				{
sl@0
   686
				// QueueTransaction requests are only supported by channels in Master mode.
sl@0
   687
				switch(chanPtr->ChannelType())
sl@0
   688
					{
sl@0
   689
					case DIicBusChannel::ESlave:
sl@0
   690
						{
sl@0
   691
						r = KErrNotSupported;
sl@0
   692
						break;
sl@0
   693
						}
sl@0
   694
					case DIicBusChannel::EMasterSlave:
sl@0
   695
						{
sl@0
   696
						r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
sl@0
   697
						if(r == KErrNone)
sl@0
   698
							{
sl@0
   699
							r = (((DIicBusChannelMasterSlave*) chanPtr)->CancelTransaction(aTransaction));
sl@0
   700
							}
sl@0
   701
						break;
sl@0
   702
						}
sl@0
   703
					case DIicBusChannel::EMaster:
sl@0
   704
						{
sl@0
   705
						r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
sl@0
   706
						if(r == KErrNone)
sl@0
   707
							{
sl@0
   708
							r = (((DIicBusChannelMaster*) chanPtr)->CancelTransaction(aTransaction));
sl@0
   709
							}
sl@0
   710
						break;
sl@0
   711
						}
sl@0
   712
					default:
sl@0
   713
						{
sl@0
   714
						r = KErrGeneral;
sl@0
   715
						}
sl@0
   716
					}
sl@0
   717
				}
sl@0
   718
			}
sl@0
   719
		}
sl@0
   720
	FreeChanReadAccess();
sl@0
   721
	return r;
sl@0
   722
	}
sl@0
   723
sl@0
   724
	// Slave-side API
sl@0
   725
TInt DIicBusController::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
sl@0
   726
	{
sl@0
   727
	// Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
sl@0
   728
	if(!aCallback || !aConfigHdr)
sl@0
   729
		{
sl@0
   730
		return KErrArgument;
sl@0
   731
		}
sl@0
   732
sl@0
   733
	// Get the channel
sl@0
   734
	TInt chanIndex = 0;
sl@0
   735
	DIicBusChannel* chanPtr = NULL;
sl@0
   736
sl@0
   737
	// Can only read the channel array if it is not currently being modified
sl@0
   738
	TInt r = GetChanReadAccess();
sl@0
   739
	if(r == KErrNone)
sl@0
   740
		{
sl@0
   741
		r = GetChanPtr(aBusId, chanIndex, chanPtr);
sl@0
   742
		if(r == KErrNone)
sl@0
   743
			{
sl@0
   744
			if(!chanPtr)
sl@0
   745
				{
sl@0
   746
				r = KErrArgument;
sl@0
   747
				}
sl@0
   748
			else
sl@0
   749
				{
sl@0
   750
				DIicBusChannelSlave* slaveChanPtr = NULL;
sl@0
   751
				switch(chanPtr->ChannelType())
sl@0
   752
					{
sl@0
   753
					// CaptureChannel requests are only supported by channels in Slave mode.
sl@0
   754
					case DIicBusChannel::EMaster:
sl@0
   755
						{
sl@0
   756
						r = KErrNotSupported;
sl@0
   757
						break;
sl@0
   758
						}
sl@0
   759
					case DIicBusChannel::EMasterSlave:
sl@0
   760
						{
sl@0
   761
						slaveChanPtr = ((DIicBusChannelMasterSlave*) chanPtr)->iSlaveChannel;
sl@0
   762
						__ASSERT_DEBUG(slaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__)); // MasterSlave channel should have a valid Slave channel
sl@0
   763
						// Send the request to the channel
sl@0
   764
						slaveChanPtr->iController = this;
sl@0
   765
						r = ((DIicBusChannelMasterSlave*) chanPtr)->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
sl@0
   766
						break;
sl@0
   767
						}
sl@0
   768
					case DIicBusChannel::ESlave:
sl@0
   769
						{
sl@0
   770
						slaveChanPtr = (DIicBusChannelSlave*) chanPtr; // chanPtr is non-NULL
sl@0
   771
						// Send the request to the channel
sl@0
   772
						slaveChanPtr->iController = this;
sl@0
   773
						r = (slaveChanPtr->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch));
sl@0
   774
						break;
sl@0
   775
						}
sl@0
   776
					default:
sl@0
   777
						{
sl@0
   778
						r = KErrArgument;
sl@0
   779
						}
sl@0
   780
					}
sl@0
   781
				// For synchronous capture, if successful then install the channel
sl@0
   782
				if(r == KErrNone && slaveChanPtr)
sl@0
   783
					{
sl@0
   784
					if(!aAsynch)
sl@0
   785
						{
sl@0
   786
						InstallCapturedChannel(aChannelId, slaveChanPtr);
sl@0
   787
						}
sl@0
   788
					}
sl@0
   789
				}
sl@0
   790
			}
sl@0
   791
		}
sl@0
   792
	FreeChanReadAccess();
sl@0
   793
	return r;
sl@0
   794
	}
sl@0
   795
sl@0
   796
sl@0
   797
TInt DIicBusController::GetSlaveChanPtr(TInt aChannelId, DIicBusChannelSlave*& aSlaveChanPtr)
sl@0
   798
	{
sl@0
   799
	TInt r=KErrNone;
sl@0
   800
	// Check that the channelID is recognised
sl@0
   801
	TCapturedChannel capturedChan(aChannelId,NULL);
sl@0
   802
	TInt chanIndex=-1;
sl@0
   803
	// Ensure the array of captured channels will not be modified before it has been searched
sl@0
   804
	// Because searches are bounded by the size of the array and do not involve allocating
sl@0
   805
	// or freeing memory, simply take the spinlock at the start of the operation and release at the end
sl@0
   806
	TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
sl@0
   807
	r=FindCapturedChanById(capturedChan, chanIndex);
sl@0
   808
	if((chanIndex < 0)||(r == KErrNotFound))
sl@0
   809
		r=KErrArgument;
sl@0
   810
	else
sl@0
   811
		aSlaveChanPtr = (DIicBusChannelSlave*)(iCapturedChannels[chanIndex].iChanPtr);
sl@0
   812
	__SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
sl@0
   813
sl@0
   814
	__ASSERT_DEBUG(aSlaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
sl@0
   815
	return r;
sl@0
   816
	}
sl@0
   817
sl@0
   818
sl@0
   819
TInt DIicBusController::ReleaseChannel(TInt aChannelId)
sl@0
   820
	{
sl@0
   821
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::ReleaseChannel, channelID = 0x%x \n",aChannelId));
sl@0
   822
	TInt r = KErrNone;
sl@0
   823
	DIicBusChannel* chanPtr = NULL;
sl@0
   824
	
sl@0
   825
	// Get the pointer to the Slave Channel
sl@0
   826
	DIicBusChannelSlave* slaveChanPtr = NULL;
sl@0
   827
	if((r = GetSlaveChanPtr(aChannelId, slaveChanPtr)) != KErrNone)
sl@0
   828
		return r;
sl@0
   829
		
sl@0
   830
	DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
sl@0
   831
	searchChannel.SetChannelNumber(slaveChanPtr->ChannelNumber());
sl@0
   832
sl@0
   833
	TInt dumIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
sl@0
   834
	if(dumIndex < 0)
sl@0
   835
		{
sl@0
   836
		return KErrNotFound;
sl@0
   837
		}
sl@0
   838
	chanPtr = iChannelArray[dumIndex];
sl@0
   839
sl@0
   840
	__ASSERT_DEBUG(chanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
sl@0
   841
sl@0
   842
	//if it is the masterslave channel, then call the masterslave's RelaseChannel
sl@0
   843
	// which will call the slave channel's ReleaseChannel internally
sl@0
   844
	if(chanPtr->ChannelType() == DIicBusChannel::EMasterSlave)
sl@0
   845
		r = ((DIicBusChannelMasterSlave*)chanPtr)->ReleaseChannel();
sl@0
   846
	else // Call the slave only ReleaseChannel
sl@0
   847
		r = slaveChanPtr->ReleaseChannel();
sl@0
   848
	
sl@0
   849
	// In either case de-install the captured slave channel
sl@0
   850
	if(r == KErrNone)
sl@0
   851
		{
sl@0
   852
		r = DeInstallCapturedChannel(aChannelId, slaveChanPtr);
sl@0
   853
		}
sl@0
   854
sl@0
   855
	// No need to unset iController - there is only one IIC Controller
sl@0
   856
	return r;
sl@0
   857
	}
sl@0
   858
sl@0
   859
sl@0
   860
TInt DIicBusController::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
sl@0
   861
	{
sl@0
   862
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterRxBuffer, channelID=0x%x,aRxBuffer=0x%x,aBufGranularity=0x%x,aNumWords=0x%x,aOffset=0x%x \n",aChannelId,(TInt)&aRxBuffer,aBufGranularity,aNumWords,aOffset));
sl@0
   863
sl@0
   864
    // Acquire the pointer to the Slave Channel
sl@0
   865
	DIicBusChannelSlave* slaveChanPtr = NULL;
sl@0
   866
	TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
sl@0
   867
	if(r != KErrNone)
sl@0
   868
		{
sl@0
   869
		return r;
sl@0
   870
		}
sl@0
   871
sl@0
   872
	// Instigate the channel functionality
sl@0
   873
	return(slaveChanPtr->RegisterRxBuffer(aRxBuffer,aBufGranularity,aNumWords,aOffset));
sl@0
   874
	}
sl@0
   875
sl@0
   876
TInt DIicBusController::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
sl@0
   877
	{
sl@0
   878
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterTxBuffer, channelID=0x%x,aTxBuffer=0x%x,aBufGranularity=0x%x,aNumWords=0x%x,aOffset=0x%x \n",aChannelId,(TInt)&aTxBuffer,aBufGranularity,aNumWords,aOffset));
sl@0
   879
sl@0
   880
	// Acquire the pointer to the Slave Channel
sl@0
   881
	DIicBusChannelSlave* slaveChanPtr = NULL;
sl@0
   882
	TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
sl@0
   883
	if(r != KErrNone)
sl@0
   884
		{
sl@0
   885
		return r;
sl@0
   886
		}
sl@0
   887
sl@0
   888
	// Instigate the channel functionality
sl@0
   889
	return (slaveChanPtr->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset));
sl@0
   890
	}
sl@0
   891
sl@0
   892
sl@0
   893
TInt DIicBusController::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
sl@0
   894
	{
sl@0
   895
    __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::SetNotificationTrigger - for aChannelId=0x%x, aTrigger=0x%x\n",aChannelId,aTrigger));
sl@0
   896
	// Acquire the pointer to the Slave Channel
sl@0
   897
	DIicBusChannelSlave* slaveChanPtr = NULL;
sl@0
   898
	TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
sl@0
   899
	if( r != KErrNone)
sl@0
   900
		{
sl@0
   901
		return r;
sl@0
   902
		}
sl@0
   903
sl@0
   904
	// Instigate the channel functionality
sl@0
   905
	return(slaveChanPtr->SetNotificationTrigger(aTrigger));
sl@0
   906
	}
sl@0
   907
sl@0
   908
sl@0
   909
TInt DIicBusController::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
sl@0
   910
	{
sl@0
   911
//		The IIC controller and channel classes are generic, and can serve many differing client and
sl@0
   912
//		bus implementations. If a client and bus make use of specific functionality that is not
sl@0
   913
//		common to other bus types, it makes sense to provide only the minimum-required support in the
sl@0
   914
//		generic code. Here, the channel identifier is checked but all other parameters are passed
sl@0
   915
//		directly to the bus implementation channel for processing; if the channel does not provide
sl@0
   916
//		StaticExtension implementation, the generic DIicBusChannel::StaticExtension method is invoked.
sl@0
   917
sl@0
   918
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   919
	if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
sl@0
   920
		{
sl@0
   921
		IIC_MSSTATEXT_START_PIL_TRACE
sl@0
   922
		}
sl@0
   923
	else if((aFunction & KControlIoMask) == KMasterControlIo)
sl@0
   924
		{
sl@0
   925
		IIC_MSTATEXT_START_PIL_TRACE
sl@0
   926
		}
sl@0
   927
	else if((aFunction & KControlIoMask) == KSlaveControlIo)
sl@0
   928
		{
sl@0
   929
		IIC_SSTATEXT_START_PIL_TRACE
sl@0
   930
		}
sl@0
   931
//	else - Unexpected value - just pass silently to the PSL ...
sl@0
   932
#endif
sl@0
   933
sl@0
   934
	// Get the channel
sl@0
   935
	TInt dumInt = 0;
sl@0
   936
	DIicBusChannel* chanPtr = NULL;
sl@0
   937
	// Can only read the channel array if it is not currently being modified
sl@0
   938
	TInt r = GetChanReadAccess();
sl@0
   939
	if(r == KErrNone)
sl@0
   940
		{
sl@0
   941
		r = GetChanPtr(aId, dumInt, chanPtr);
sl@0
   942
		if(r == KErrNone)
sl@0
   943
			{
sl@0
   944
			if(!chanPtr)
sl@0
   945
				{
sl@0
   946
				r = KErrArgument;
sl@0
   947
				}
sl@0
   948
			else
sl@0
   949
				{
sl@0
   950
				r = chanPtr->StaticExtension(aFunction, aParam1, aParam2);
sl@0
   951
				}
sl@0
   952
			}
sl@0
   953
		}
sl@0
   954
sl@0
   955
#ifdef IIC_INSTRUMENTATION_MACRO
sl@0
   956
	if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
sl@0
   957
		{
sl@0
   958
		IIC_MSSTATEXT_START_PIL_TRACE
sl@0
   959
		}
sl@0
   960
	else if((aFunction & KControlIoMask) == KMasterControlIo)
sl@0
   961
		{
sl@0
   962
		IIC_MSTATEXT_START_PIL_TRACE
sl@0
   963
		}
sl@0
   964
	else if((aFunction & KControlIoMask) == KSlaveControlIo)
sl@0
   965
		{
sl@0
   966
		IIC_SSTATEXT_START_PIL_TRACE
sl@0
   967
		}
sl@0
   968
//	else	... do nothing
sl@0
   969
#endif
sl@0
   970
	FreeChanReadAccess();
sl@0
   971
	return r;
sl@0
   972
	}
sl@0
   973
sl@0
   974
sl@0
   975
#ifdef _DEBUG
sl@0
   976
sl@0
   977
void DIicBusController::DumpCapturedChannels()
sl@0
   978
	{
sl@0
   979
	// Print iCapturedChannels ...
sl@0
   980
	TInt count=0;
sl@0
   981
	TInt i=0;
sl@0
   982
	TCapturedChannel emptyChan;
sl@0
   983
	for(;i<KMaxNumCapturedChannels;++i)
sl@0
   984
		{
sl@0
   985
		if(iCapturedChannels[i] == emptyChan)
sl@0
   986
			continue;
sl@0
   987
		++count;
sl@0
   988
		}
sl@0
   989
sl@0
   990
	i = 0;
sl@0
   991
    __KTRACE_OPT(KIIC, Kern::Printf("	- Count gave %d\n",count));
sl@0
   992
	for(;i<KMaxNumCapturedChannels;++i)
sl@0
   993
		{
sl@0
   994
		if(iCapturedChannels[i] == emptyChan)
sl@0
   995
			continue;
sl@0
   996
		DIicBusChannel* ptr=(DIicBusChannel*)(iCapturedChannels[i]).iChanPtr;
sl@0
   997
	    __KTRACE_OPT(KIIC, Kern::Printf("	- ptr %d=0x%x\n",i,ptr));
sl@0
   998
		ptr->StaticExtension(KCtrlIoDumpChan,0,0);
sl@0
   999
		};
sl@0
  1000
	}
sl@0
  1001
sl@0
  1002
void DIicBusController::DumpChannelArray()
sl@0
  1003
	{
sl@0
  1004
	TInt i = 0;
sl@0
  1005
	__KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::DumpChannelArray\n"));
sl@0
  1006
    __KTRACE_OPT(KIIC, Kern::Printf("	- Count gave %d\n",iChannelArray.Count()));
sl@0
  1007
	for(i=0; i<iChannelArray.Count(); i++)
sl@0
  1008
		{
sl@0
  1009
		DIicBusChannel* ptr=iChannelArray[i];
sl@0
  1010
	    __KTRACE_OPT(KIIC, Kern::Printf("	- ptr %d=0x%x\n",i,ptr));
sl@0
  1011
		ptr->StaticExtension(KCtrlIoDumpChan,0,0);
sl@0
  1012
		};
sl@0
  1013
	}
sl@0
  1014
sl@0
  1015
#endif
sl@0
  1016
sl@0
  1017
#ifdef IIC_SIMULATED_PSL
sl@0
  1018
TVersion DIicPdd::VersionRequired()
sl@0
  1019
	{
sl@0
  1020
	const TInt KIicMajorVersionNumber=1;
sl@0
  1021
	const TInt KIicMinorVersionNumber=0;
sl@0
  1022
	const TInt KIicBuildVersionNumber=KE32BuildVersionNumber;
sl@0
  1023
	return TVersion(KIicMajorVersionNumber,KIicMinorVersionNumber,KIicBuildVersionNumber);
sl@0
  1024
	}
sl@0
  1025
sl@0
  1026
/** Factory class constructor */
sl@0
  1027
DIicPdd::DIicPdd()
sl@0
  1028
	{
sl@0
  1029
    iVersion = DIicPdd::VersionRequired();
sl@0
  1030
	}
sl@0
  1031
sl@0
  1032
DIicPdd::~DIicPdd()
sl@0
  1033
	{
sl@0
  1034
	delete TheController;
sl@0
  1035
	}
sl@0
  1036
sl@0
  1037
TInt DIicPdd::Install()
sl@0
  1038
    {
sl@0
  1039
    return(SetName(&KPddName));
sl@0
  1040
    }
sl@0
  1041
sl@0
  1042
/**  Called by the kernel's device driver framework to create a Physical Channel. */
sl@0
  1043
TInt DIicPdd::Create(DBase*& /*aChannel*/, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
sl@0
  1044
    {
sl@0
  1045
    return KErrNone;
sl@0
  1046
    }
sl@0
  1047
sl@0
  1048
/**  Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
sl@0
  1049
TInt DIicPdd::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
sl@0
  1050
    {
sl@0
  1051
   	if (!Kern::QueryVersionSupported(DIicPdd::VersionRequired(),aVer))
sl@0
  1052
		return(KErrNotSupported);
sl@0
  1053
    return KErrNone;
sl@0
  1054
    }
sl@0
  1055
sl@0
  1056
/** Return the driver capabilities */
sl@0
  1057
void DIicPdd::GetCaps(TDes8& aDes) const
sl@0
  1058
    {
sl@0
  1059
	// Create a capabilities object
sl@0
  1060
	TCaps caps;
sl@0
  1061
	caps.iVersion = iVersion;
sl@0
  1062
	// Zero the buffer
sl@0
  1063
	TInt maxLen = aDes.MaxLength();
sl@0
  1064
	aDes.FillZ(maxLen);
sl@0
  1065
	// Copy cpabilities
sl@0
  1066
	TInt size=sizeof(caps);
sl@0
  1067
	if(size>maxLen)
sl@0
  1068
	   size=maxLen;
sl@0
  1069
	aDes.Copy((TUint8*)&caps,size);
sl@0
  1070
    }
sl@0
  1071
#endif
sl@0
  1072
sl@0
  1073
#ifndef IIC_SIMULATED_PSL
sl@0
  1074
// Client interface entry point
sl@0
  1075
DECLARE_EXTENSION_WITH_PRIORITY(KExtensionMaximumPriority-1)	// highest priority after Resource Manager
sl@0
  1076
	{
sl@0
  1077
	TheController = new DIicBusController;
sl@0
  1078
	if(!TheController)
sl@0
  1079
		return KErrNoMemory;
sl@0
  1080
	TInt r=TheController->Create();
sl@0
  1081
	return r;
sl@0
  1082
	}
sl@0
  1083
#else
sl@0
  1084
static DIicPdd* TheIicPdd;
sl@0
  1085
sl@0
  1086
DECLARE_STANDARD_PDD()
sl@0
  1087
	{
sl@0
  1088
	TheController = new DIicBusController;
sl@0
  1089
	if(!TheController)
sl@0
  1090
		return NULL;
sl@0
  1091
	TInt r = TheController->Create();
sl@0
  1092
	if(r == KErrNone)
sl@0
  1093
		{
sl@0
  1094
		TheIicPdd = new DIicPdd;
sl@0
  1095
		if(TheIicPdd)
sl@0
  1096
			return TheIicPdd;
sl@0
  1097
		}
sl@0
  1098
	
sl@0
  1099
	delete TheController; 
sl@0
  1100
	return NULL;
sl@0
  1101
	}
sl@0
  1102
#endif
sl@0
  1103
sl@0
  1104
sl@0
  1105