1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/iic/iic.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1105 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\drivers\iic.cpp
1.18 +// IIC Controller and public API Implementation
1.19 +//
1.20 +
1.21 +#include <drivers/iic.h>
1.22 +#include <drivers/iic_channel.h>
1.23 +#include "iic_priv.h"
1.24 +
1.25 +#ifdef IIC_INSTRUMENTATION_MACRO
1.26 +#include <drivers/iic_trace.h>
1.27 +#endif
1.28 +
1.29 +// Global Controller pointer
1.30 +static DIicBusController* TheController = NULL;
1.31 +
1.32 +//
1.33 +// Implementation of generic IicBus API for client interface
1.34 +//
1.35 +EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1.36 + {
1.37 +#ifdef IIC_INSTRUMENTATION_MACRO
1.38 + IIC_MQTRANSSYNC_START_PIL_TRACE;
1.39 +#endif
1.40 + TInt r=TheController->QueueTransaction(aBusId, aTransaction);
1.41 +
1.42 +#ifdef IIC_INSTRUMENTATION_MACRO
1.43 + IIC_MQTRANSSYNC_END_PIL_TRACE;
1.44 +#endif
1.45 + return r;
1.46 + }
1.47 +
1.48 +EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
1.49 + {
1.50 +#ifdef IIC_INSTRUMENTATION_MACRO
1.51 + IIC_MQTRANSASYNC_START_PIL_TRACE;
1.52 +#endif
1.53 + TInt r=TheController->QueueTransaction(aBusId, aTransaction, aCallback);
1.54 +
1.55 +#ifdef IIC_INSTRUMENTATION_MACRO
1.56 + IIC_MQTRANSASYNC_END_PIL_TRACE;
1.57 +#endif
1.58 + return r;
1.59 + }
1.60 +
1.61 +EXPORT_C TInt IicBus::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1.62 + {
1.63 +#ifdef IIC_INSTRUMENTATION_MACRO
1.64 + IIC_MCANCELTRANS_START_PIL_TRACE;
1.65 +#endif
1.66 + TInt r=TheController->CancelTransaction(aBusId, aTransaction);
1.67 +
1.68 +#ifdef IIC_INSTRUMENTATION_MACRO
1.69 + IIC_MCANCELTRANS_END_PIL_TRACE;
1.70 +#endif
1.71 + return r;
1.72 + }
1.73 +
1.74 +EXPORT_C TInt IicBus::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
1.75 + {
1.76 +#ifdef IIC_INSTRUMENTATION_MACRO
1.77 + if(!aAsynch)
1.78 + {
1.79 + IIC_SCAPTCHANSYNC_START_PIL_TRACE;
1.80 + }
1.81 + else
1.82 + {
1.83 + IIC_SCAPTCHANASYNC_START_PIL_TRACE;
1.84 + }
1.85 +#endif
1.86 + TInt r=TheController->CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
1.87 +
1.88 +#ifdef IIC_INSTRUMENTATION_MACRO
1.89 + if(!aAsynch)
1.90 + {
1.91 + IIC_SCAPTCHANSYNC_END_PIL_TRACE;
1.92 + }
1.93 +#endif
1.94 + return r;
1.95 + }
1.96 +
1.97 +EXPORT_C TInt IicBus::ReleaseChannel(TInt aChannelId)
1.98 + {
1.99 +#ifdef IIC_INSTRUMENTATION_MACRO
1.100 + IIC_SRELCHAN_START_PIL_TRACE;
1.101 +#endif
1.102 + TInt r=TheController->ReleaseChannel(aChannelId);
1.103 +
1.104 +#ifdef IIC_INSTRUMENTATION_MACRO
1.105 + IIC_SRELCHAN_END_PIL_TRACE;
1.106 +#endif
1.107 + return r;
1.108 + }
1.109 +
1.110 +EXPORT_C TInt IicBus::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
1.111 + {
1.112 +#ifdef IIC_INSTRUMENTATION_MACRO
1.113 + IIC_SREGRXBUF_START_PIL_TRACE;
1.114 +#endif
1.115 + TInt r=TheController->RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
1.116 +
1.117 +#ifdef IIC_INSTRUMENTATION_MACRO
1.118 + IIC_SREGRXBUF_END_PIL_TRACE;
1.119 +#endif
1.120 + return r;
1.121 + }
1.122 +
1.123 +EXPORT_C TInt IicBus::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
1.124 + {
1.125 +#ifdef IIC_INSTRUMENTATION_MACRO
1.126 + IIC_SREGTXBUF_START_PIL_TRACE;
1.127 +#endif
1.128 + TInt r=TheController->RegisterTxBuffer(aChannelId, aTxBuffer, aBufGranularity, aNumWords, aOffset);
1.129 +
1.130 +#ifdef IIC_INSTRUMENTATION_MACRO
1.131 + IIC_SREGTXBUF_END_PIL_TRACE;
1.132 +#endif
1.133 + return r;
1.134 + }
1.135 +
1.136 +EXPORT_C TInt IicBus::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
1.137 + {
1.138 +#ifdef IIC_INSTRUMENTATION_MACRO
1.139 + IIC_SNOTIFTRIG_START_PIL_TRACE;
1.140 +#endif
1.141 + TInt r=TheController->SetNotificationTrigger(aChannelId, aTrigger);
1.142 +
1.143 +#ifdef IIC_INSTRUMENTATION_MACRO
1.144 + IIC_SNOTIFTRIG_END_PIL_TRACE;
1.145 +#endif
1.146 + return r;
1.147 + }
1.148 +
1.149 +EXPORT_C TInt IicBus::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
1.150 + {
1.151 + return(TheController->StaticExtension(aId, aFunction, aParam1, aParam2));
1.152 + }
1.153 +
1.154 +
1.155 +//
1.156 +// Bus Controller
1.157 +//
1.158 +
1.159 +// auxiliary function for ordering entries in the array of channels
1.160 +TInt DIicBusController::OrderEntries(const DIicBusChannel& aMatch, const DIicBusChannel& aEntry)
1.161 + {
1.162 + TUint8 l=(TUint8)aMatch.ChannelNumber();
1.163 + TUint8 r=(TUint8)aEntry.ChannelNumber();
1.164 + if(l>r)
1.165 + return -1;
1.166 + else if(l<r)
1.167 + return 1;
1.168 + else
1.169 + return 0;
1.170 + }
1.171 +
1.172 +// global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
1.173 +TLinearOrder<DIicBusChannel> EntryOrder(DIicBusController::OrderEntries);
1.174 +
1.175 +// Implementation for DIicBusController
1.176 +//
1.177 +
1.178 +TInt DIicBusController::Create()
1.179 + {
1.180 + TInt r=KErrNone;
1.181 + iChanLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2); // Semi-arbitrary, low priority value
1.182 + iCaptLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2); // Semi-arbitrary, low priority value
1.183 + if((iChanLock == NULL)||(iCaptLock == NULL))
1.184 + {
1.185 + delete iChanLock;
1.186 + delete iCaptLock;
1.187 + r=KErrNoMemory;
1.188 + }
1.189 + return r;
1.190 + }
1.191 +
1.192 +DIicBusController::~DIicBusController()
1.193 + {
1.194 +#ifdef IIC_SIMULATED_PSL
1.195 + for(TInt i=0; i<iChannelArray.Count(); i++)
1.196 + {
1.197 + DIicBusChannel* ptr=iChannelArray[i];
1.198 + // Remove the channel from the array
1.199 + iChannelArray.Remove(i);
1.200 + // Delete the channel object
1.201 + delete ptr;
1.202 + };
1.203 +
1.204 + iChannelArray.Reset();
1.205 + delete iChanLock;
1.206 + delete iCaptLock;
1.207 +#endif
1.208 + }
1.209 +
1.210 +TInt DIicBusController::GetChanWriteAccess()
1.211 + {
1.212 + // Can only have one insertion or removal active at any one time
1.213 + // Can not perform an insertion or removal while a read is in progress
1.214 + // If either of the two above conditions exist, return KErrInUse
1.215 + // Otherwise, set the flag to indicate that a write is in progress
1.216 + // and return KErrNone.
1.217 + TInt chanIntState=0;
1.218 + chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
1.219 + if(iChanRwFlags != 0)
1.220 + {
1.221 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.222 + return KErrInUse;
1.223 + }
1.224 + iChanRwFlags |= EWriteInProgress;
1.225 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.226 + return KErrNone;
1.227 + }
1.228 +
1.229 +void DIicBusController::FreeChanWriteAccess()
1.230 + {
1.231 + // If an insertion or removal is in progress, no other modifying operation
1.232 + // can be active. Reads are also not permitted - so iChanRwFlags can only be
1.233 + // EWriteInProgress.
1.234 + __ASSERT_DEBUG(iChanRwFlags == EWriteInProgress, Kern::Fault(KIicPanic,__LINE__));
1.235 + TInt chanIntState=0;
1.236 + chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
1.237 + iChanRwFlags &= ~EWriteInProgress;
1.238 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.239 + }
1.240 +
1.241 +TInt DIicBusController::GetChanReadAccess()
1.242 + {
1.243 + // No reads are permitted while an insertion or removal is in progress
1.244 + // If one of the above operations is in progress return KErrInUse
1.245 + // Can have several concurrent reads at any one time - so increment
1.246 + // the count of such operations as well as ensuring the flag is set to indicate
1.247 + // a read is in progress
1.248 + TInt chanIntState=0;
1.249 + chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
1.250 + if(iChanRwFlags == EWriteInProgress)
1.251 + {
1.252 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.253 + return KErrInUse;
1.254 + }
1.255 + __ASSERT_DEBUG(iChanRdCount!=0xFFFFFFFF, Kern::Fault(KIicPanic,__LINE__)); // Overflow
1.256 + iChanRdCount++;
1.257 + iChanRwFlags |= EReadInProgress;
1.258 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.259 + return KErrNone;
1.260 + }
1.261 +
1.262 +void DIicBusController::FreeChanReadAccess()
1.263 + {
1.264 + // No insertions or removals are permitted while a read is in progress
1.265 + // so iChanRwFlags can only be EReadInProgress
1.266 + // Multiple reads can be in progress concurrently, so the count must be decremented
1.267 + TInt chanIntState=0;
1.268 + chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
1.269 + __ASSERT_DEBUG(iChanRwFlags == EReadInProgress, Kern::Fault(KIicPanic,__LINE__));
1.270 + __ASSERT_DEBUG(iChanRdCount>0, Kern::Fault(KIicPanic,__LINE__));
1.271 + iChanRdCount--;
1.272 + if(iChanRdCount == 0)
1.273 + iChanRwFlags &= ~EReadInProgress;
1.274 + __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
1.275 + }
1.276 +
1.277 +TInt DIicBusController::RequestTypeSupported(const TInt aBusId, DIicBusChannelMaster* const aChannel)
1.278 + {
1.279 + TInt32 reqBusType;
1.280 + reqBusType = GET_BUS_TYPE(aBusId);
1.281 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RequestTypeSupported, BusType=0x%x\n", reqBusType));
1.282 +
1.283 + if(reqBusType != aChannel->BusType())
1.284 + {
1.285 + return KErrNotSupported;
1.286 + }
1.287 +
1.288 + return KErrNone;
1.289 + }
1.290 +
1.291 +
1.292 +EXPORT_C TInt DIicBusController::RegisterChannels(DIicBusChannel** aListChannels, TInt aNumberChannels)
1.293 + {
1.294 +// To be used by Channel implementations to register a list of supported channels
1.295 + __KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::RegisterChannels, aListChannels=0x%x, aNumberChannels=%d\n",aListChannels,aNumberChannels));
1.296 + __ASSERT_DEBUG(aListChannels!=NULL, Kern::Fault(KIicPanic,__LINE__));
1.297 +
1.298 + RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
1.299 +
1.300 +#ifdef IIC_INSTRUMENTATION_MACRO
1.301 + IIC_REGISTERCHANS_START_PIL_TRACE;
1.302 +#endif
1.303 + // Get access to the channel pointer array - exit if it is currently being modfied
1.304 + TInt r=KErrNone;
1.305 + if((r=TheController->GetChanWriteAccess()) == KErrNone)
1.306 + {
1.307 +#ifdef _DEBUG
1.308 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On entry, iChannelArray ...\n"));
1.309 + TheController->DumpChannelArray();
1.310 +#endif
1.311 + // Loop for aNumberChannels and write directly to the channel array
1.312 + DIicBusChannel** chanIterator = aListChannels;
1.313 + for(TInt iteration = 0; iteration < aNumberChannels; ++iteration, ++chanIterator)
1.314 + {
1.315 + DIicBusChannel* chanPtr = *chanIterator;
1.316 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - adding channel number %d\n",chanPtr->ChannelNumber()));
1.317 + TInt r = chanArray->InsertInOrder(chanPtr,EntryOrder);
1.318 + if(r!=KErrNone)
1.319 + break;
1.320 + }
1.321 +
1.322 +#ifdef _DEBUG
1.323 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On exit, iChannelArray ...\n"));
1.324 + TheController->DumpChannelArray();
1.325 +#endif
1.326 + TheController->FreeChanWriteAccess();
1.327 + }
1.328 + else
1.329 + {
1.330 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanWriteAccess returned %d\n",r));
1.331 + }
1.332 +
1.333 +#ifdef IIC_INSTRUMENTATION_MACRO
1.334 + IIC_REGISTERCHANS_END_PIL_TRACE;
1.335 +#endif
1.336 + return r;
1.337 + }
1.338 +
1.339 +
1.340 +EXPORT_C TInt DIicBusController::DeRegisterChannel(DIicBusChannel* aChannel)
1.341 + {
1.342 +// To be used by Channel implementations to deregister a channel
1.343 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel, aChannel=0x%x\n",aChannel));
1.344 + if(aChannel == NULL)
1.345 + return KErrArgument;
1.346 +
1.347 + RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
1.348 +
1.349 +#ifdef IIC_INSTRUMENTATION_MACRO
1.350 + IIC_DEREGISTERCHAN_START_PIL_TRACE;
1.351 +#endif
1.352 + TInt r=KErrNone;
1.353 + // Get access to the channel pointer array - exit if it is currently unavailable
1.354 + // Gaining write access will prevent a client of a Master Channel from instigating a new QueueTransaction
1.355 + // (or CancelTransaction), and it will obstruct a client of a Slave Channel in CaptureChannel.
1.356 + if((r=TheController->GetChanWriteAccess())!=KErrNone)
1.357 + return r;
1.358 +
1.359 + // Check channel is registered
1.360 + TInt chanIndex = chanArray->FindInOrder(aChannel,EntryOrder);
1.361 + if(chanIndex<0)
1.362 + {
1.363 + TheController->FreeChanWriteAccess();
1.364 + return KErrNotFound;
1.365 + }
1.366 +
1.367 +#ifdef _DEBUG
1.368 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On entry, iChannelArray ...\n"));
1.369 + TheController->DumpChannelArray();
1.370 +#endif
1.371 +
1.372 + // Remove the channel from the array
1.373 + // Note that this does not delete the channel object
1.374 + chanArray->Remove(chanIndex);
1.375 +
1.376 +#ifdef _DEBUG
1.377 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On exit, iChannelArray ...\n"));
1.378 + TheController->DumpChannelArray();
1.379 +#endif
1.380 + TheController->FreeChanWriteAccess();
1.381 +
1.382 +#ifdef IIC_INSTRUMENTATION_MACRO
1.383 + IIC_DEREGISTERCHAN_END_PIL_TRACE;
1.384 +#endif
1.385 + return KErrNone;
1.386 + }
1.387 +
1.388 +TInt DIicBusController::FindCapturedChanById(TCapturedChannel aCapturedChan, TInt& aIndex)
1.389 + {
1.390 + TInt index=0;
1.391 + TInt r=KErrNotFound;
1.392 + do
1.393 + {
1.394 + if(iCapturedChannels[index].iChannelId == aCapturedChan.iChannelId)
1.395 + {
1.396 + aIndex=index;
1.397 + r=KErrNone;
1.398 + }
1.399 + index++;
1.400 + } while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
1.401 + return r;
1.402 + }
1.403 +
1.404 +TInt DIicBusController::FindCapturedChan(TCapturedChannel aCapturedChan, TInt& aIndex)
1.405 + {
1.406 + TInt index=0;
1.407 + TInt r=KErrNotFound;
1.408 + do
1.409 + {
1.410 + if(iCapturedChannels[index] == aCapturedChan)
1.411 + {
1.412 + aIndex=index;
1.413 + r=KErrNone;
1.414 + }
1.415 + index++;
1.416 + } while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
1.417 + return r;
1.418 + }
1.419 +
1.420 +TInt DIicBusController::InsertCaptChanInArray(TCapturedChannel aCapturedChan)
1.421 + {
1.422 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InsertCaptChanInArray \n"));
1.423 + // Ensure the channel hasn't already been inserted in the array
1.424 + // If found, fault the Kernel
1.425 + TInt dumInt = 0;
1.426 + TInt r=FindCapturedChan(aCapturedChan,dumInt);
1.427 + __ASSERT_DEBUG(r!=KErrNone, Kern::Fault(KIicPanic,__LINE__));
1.428 +
1.429 + // Loop the array and insert in the first available slot
1.430 + // If no slots are available return KErrNotReady
1.431 + TInt index=0;
1.432 + TCapturedChannel emptyChan;
1.433 + for(;index<KMaxNumCapturedChannels;++index)
1.434 + {
1.435 + if(iCapturedChannels[index] == emptyChan)
1.436 + {
1.437 + // Found a space
1.438 + iCapturedChannels[index]=aCapturedChan;
1.439 + break;
1.440 + }
1.441 + }
1.442 + if(index>=KMaxNumCapturedChannels)
1.443 + r = KErrNotReady;
1.444 + return r;
1.445 + }
1.446 +
1.447 +TInt DIicBusController::RemoveCaptChanFromArray(TCapturedChannel aCapturedChan)
1.448 + {
1.449 + // Remove the entry from the array
1.450 + // If the entry is not present return KErrArgument
1.451 + TInt index=-1;
1.452 + TInt r=FindCapturedChan(aCapturedChan,index);
1.453 + if((r!=KErrNone)||(index>=KMaxNumCapturedChannels))
1.454 + return KErrArgument;
1.455 + iCapturedChannels[index].iChanPtr=NULL;
1.456 + iCapturedChannels[index].iChannelId=0;
1.457 + return KErrNone;
1.458 + }
1.459 +
1.460 +
1.461 +TInt DIicBusController::InstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
1.462 + {
1.463 +#ifdef _DEBUG
1.464 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On entry, iCapturedChannels ...\n"));
1.465 + DumpCapturedChannels();
1.466 +#endif
1.467 + TInt r=KErrNone;
1.468 + TCapturedChannel capturedChan((TInt)aChannelId,(DIicBusChannelSlave*)aChanPtr);
1.469 + // Because insertions are bounded by the size of the array and do not involve allocating
1.470 + // or freeing memory, simply take the spinlock at the start of the operation and release at the end
1.471 + TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
1.472 + r=InsertCaptChanInArray(capturedChan);
1.473 + __SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
1.474 + if(r!=KErrNone)
1.475 + return r;
1.476 +
1.477 +#ifdef _DEBUG
1.478 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On exit, iCapturedChannels ...\n"));
1.479 + DumpCapturedChannels();
1.480 +#endif
1.481 + return KErrNone;
1.482 + }
1.483 +
1.484 +TInt DIicBusController::DeInstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
1.485 + {
1.486 +#ifdef _DEBUG
1.487 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On entry, iCapturedChannels ...\n"));
1.488 + DumpCapturedChannels();
1.489 +#endif
1.490 + TInt r = KErrNone;
1.491 + TCapturedChannel capturedChan((TInt) aChannelId, (DIicBusChannelSlave*) aChanPtr);
1.492 + // Because removals are bounded by the size of the array and do not involve allocating
1.493 + // or freeing memory, simply take the spinlock at the start of the operation and release at the end
1.494 + TInt captIntState = __SPIN_LOCK_IRQSAVE(*iCaptLock);
1.495 + r = RemoveCaptChanFromArray(capturedChan);
1.496 + __SPIN_UNLOCK_IRQRESTORE(*iCaptLock, captIntState);
1.497 + if(r != KErrNone)
1.498 + return r;
1.499 +
1.500 +#ifdef _DEBUG
1.501 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On exit, iCapturedChannels ...\n"));
1.502 + DumpCapturedChannels();
1.503 +#endif
1.504 + return KErrNone;
1.505 + }
1.506 +
1.507 + // Master-side API
1.508 +TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1.509 + {
1.510 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1.511 + if(!aTransaction)
1.512 + {
1.513 + return KErrArgument;
1.514 + }
1.515 +
1.516 + // Get a pointer to the channel
1.517 + TInt dumInt = 0;
1.518 + DIicBusChannel* chanPtr = NULL;
1.519 + // Can only read the channel array if it is not currently being modified
1.520 + TInt r = GetChanReadAccess();
1.521 + if(r != KErrNone)
1.522 + {
1.523 + return r;
1.524 + }
1.525 + r = GetChanPtr(aBusId, dumInt, chanPtr);
1.526 + if(r == KErrNone)
1.527 + {
1.528 + if(!chanPtr)
1.529 + {
1.530 + r = KErrArgument;
1.531 + }
1.532 + else
1.533 + {
1.534 + switch(chanPtr->ChannelType())
1.535 + {
1.536 + // QueueTransaction requests are only supported by channels in Master mode.
1.537 + case DIicBusChannel::ESlave:
1.538 + {
1.539 + r = KErrNotSupported;
1.540 + break;
1.541 + }
1.542 + // If the request is supported by the Master channel, send it to the channel for processing in its thread
1.543 + case DIicBusChannel::EMasterSlave:
1.544 + {
1.545 + r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
1.546 + if(r == KErrNone)
1.547 + {
1.548 + aTransaction->iBusId = aBusId;
1.549 + r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction));
1.550 + }
1.551 + break;
1.552 + }
1.553 + case DIicBusChannel::EMaster:
1.554 + {
1.555 + r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
1.556 + if(r == KErrNone)
1.557 + {
1.558 + aTransaction->iBusId = aBusId;
1.559 + r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction));
1.560 + }
1.561 + break;
1.562 + }
1.563 + default:
1.564 + {
1.565 + r = KErrGeneral;
1.566 + }
1.567 + }
1.568 + }
1.569 + }
1.570 + FreeChanReadAccess();
1.571 + return r;
1.572 + }
1.573 +
1.574 +TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
1.575 + {
1.576 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x,aCallback=0x%x\n",aBusId,aTransaction,aCallback));
1.577 + if(!aTransaction || !aCallback)
1.578 + {
1.579 + return KErrArgument;
1.580 + }
1.581 +
1.582 + // Get a pointer to the channel
1.583 + TInt dumInt = 0;
1.584 + DIicBusChannel* chanPtr = NULL;
1.585 + // Can only read the channel array if it is not currently being modified
1.586 + TInt r = GetChanReadAccess();
1.587 + if(r == KErrNone)
1.588 + {
1.589 + r = GetChanPtr(aBusId, dumInt, chanPtr);
1.590 + if(r == KErrNone)
1.591 + {
1.592 + if(!chanPtr)
1.593 + {
1.594 + r = KErrArgument;
1.595 + }
1.596 + else
1.597 + {
1.598 + switch(chanPtr->ChannelType())
1.599 + {
1.600 + // QueueTransaction requests are only supported by channels in Master mode.
1.601 + case DIicBusChannel::ESlave:
1.602 + {
1.603 + r = KErrNotSupported;
1.604 + break;
1.605 + }
1.606 + // If the request is supported by the Master channel, send it to the channel for processing in its thread
1.607 + case DIicBusChannel::EMasterSlave:
1.608 + {
1.609 + r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
1.610 + if(r == KErrNone)
1.611 + {
1.612 + aTransaction->iBusId = aBusId;
1.613 + r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction, aCallback));
1.614 + }
1.615 + break;
1.616 + }
1.617 + case DIicBusChannel::EMaster:
1.618 + {
1.619 + r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
1.620 + if(r == KErrNone)
1.621 + {
1.622 + aTransaction->iBusId = aBusId;
1.623 + r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction, aCallback));
1.624 + }
1.625 + break;
1.626 + }
1.627 + default:
1.628 + {
1.629 + r = KErrGeneral;
1.630 + }
1.631 + }
1.632 + }
1.633 + }
1.634 + }
1.635 + FreeChanReadAccess();
1.636 + return r;
1.637 + }
1.638 +
1.639 +
1.640 +TInt DIicBusController::GetChanPtr(const TInt aBusId, TInt &aIndex, DIicBusChannel*& aChan)
1.641 + {
1.642 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, aBusId=0x%x\n",aBusId));
1.643 +
1.644 + TInt32 chanId;
1.645 + chanId = GET_CHAN_NUM(aBusId);
1.646 +
1.647 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanId=0x%x\n", chanId));
1.648 + DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
1.649 + searchChannel.SetChannelNumber((TInt8)chanId);
1.650 +
1.651 + TInt r = KErrNotFound;
1.652 + aIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
1.653 + if(aIndex >= 0)
1.654 + {
1.655 + aChan = iChannelArray[aIndex];
1.656 + r = KErrNone;
1.657 + }
1.658 +
1.659 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanPtr=0x%x, index=%d\n", aChan, aIndex));
1.660 + return r;
1.661 + }
1.662 +
1.663 +
1.664 +TInt DIicBusController::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
1.665 + {
1.666 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
1.667 + if(!aTransaction)
1.668 + {
1.669 + return KErrArgument;
1.670 + }
1.671 +
1.672 + // Get the channel
1.673 + TInt dumInt = 0;
1.674 + DIicBusChannel* chanPtr = NULL;
1.675 +
1.676 + // Can only read the channel array if it is not currently being modified
1.677 + TInt r = GetChanReadAccess();
1.678 + if(r == KErrNone)
1.679 + {
1.680 + r = GetChanPtr(aBusId, dumInt, chanPtr);
1.681 + if(r == KErrNone)
1.682 + {
1.683 + if(!chanPtr)
1.684 + {
1.685 + r = KErrArgument;
1.686 + }
1.687 + else
1.688 + {
1.689 + // QueueTransaction requests are only supported by channels in Master mode.
1.690 + switch(chanPtr->ChannelType())
1.691 + {
1.692 + case DIicBusChannel::ESlave:
1.693 + {
1.694 + r = KErrNotSupported;
1.695 + break;
1.696 + }
1.697 + case DIicBusChannel::EMasterSlave:
1.698 + {
1.699 + r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
1.700 + if(r == KErrNone)
1.701 + {
1.702 + r = (((DIicBusChannelMasterSlave*) chanPtr)->CancelTransaction(aTransaction));
1.703 + }
1.704 + break;
1.705 + }
1.706 + case DIicBusChannel::EMaster:
1.707 + {
1.708 + r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
1.709 + if(r == KErrNone)
1.710 + {
1.711 + r = (((DIicBusChannelMaster*) chanPtr)->CancelTransaction(aTransaction));
1.712 + }
1.713 + break;
1.714 + }
1.715 + default:
1.716 + {
1.717 + r = KErrGeneral;
1.718 + }
1.719 + }
1.720 + }
1.721 + }
1.722 + }
1.723 + FreeChanReadAccess();
1.724 + return r;
1.725 + }
1.726 +
1.727 + // Slave-side API
1.728 +TInt DIicBusController::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
1.729 + {
1.730 + // Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
1.731 + if(!aCallback || !aConfigHdr)
1.732 + {
1.733 + return KErrArgument;
1.734 + }
1.735 +
1.736 + // Get the channel
1.737 + TInt chanIndex = 0;
1.738 + DIicBusChannel* chanPtr = NULL;
1.739 +
1.740 + // Can only read the channel array if it is not currently being modified
1.741 + TInt r = GetChanReadAccess();
1.742 + if(r == KErrNone)
1.743 + {
1.744 + r = GetChanPtr(aBusId, chanIndex, chanPtr);
1.745 + if(r == KErrNone)
1.746 + {
1.747 + if(!chanPtr)
1.748 + {
1.749 + r = KErrArgument;
1.750 + }
1.751 + else
1.752 + {
1.753 + DIicBusChannelSlave* slaveChanPtr = NULL;
1.754 + switch(chanPtr->ChannelType())
1.755 + {
1.756 + // CaptureChannel requests are only supported by channels in Slave mode.
1.757 + case DIicBusChannel::EMaster:
1.758 + {
1.759 + r = KErrNotSupported;
1.760 + break;
1.761 + }
1.762 + case DIicBusChannel::EMasterSlave:
1.763 + {
1.764 + slaveChanPtr = ((DIicBusChannelMasterSlave*) chanPtr)->iSlaveChannel;
1.765 + __ASSERT_DEBUG(slaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__)); // MasterSlave channel should have a valid Slave channel
1.766 + // Send the request to the channel
1.767 + slaveChanPtr->iController = this;
1.768 + r = ((DIicBusChannelMasterSlave*) chanPtr)->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
1.769 + break;
1.770 + }
1.771 + case DIicBusChannel::ESlave:
1.772 + {
1.773 + slaveChanPtr = (DIicBusChannelSlave*) chanPtr; // chanPtr is non-NULL
1.774 + // Send the request to the channel
1.775 + slaveChanPtr->iController = this;
1.776 + r = (slaveChanPtr->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch));
1.777 + break;
1.778 + }
1.779 + default:
1.780 + {
1.781 + r = KErrArgument;
1.782 + }
1.783 + }
1.784 + // For synchronous capture, if successful then install the channel
1.785 + if(r == KErrNone && slaveChanPtr)
1.786 + {
1.787 + if(!aAsynch)
1.788 + {
1.789 + InstallCapturedChannel(aChannelId, slaveChanPtr);
1.790 + }
1.791 + }
1.792 + }
1.793 + }
1.794 + }
1.795 + FreeChanReadAccess();
1.796 + return r;
1.797 + }
1.798 +
1.799 +
1.800 +TInt DIicBusController::GetSlaveChanPtr(TInt aChannelId, DIicBusChannelSlave*& aSlaveChanPtr)
1.801 + {
1.802 + TInt r=KErrNone;
1.803 + // Check that the channelID is recognised
1.804 + TCapturedChannel capturedChan(aChannelId,NULL);
1.805 + TInt chanIndex=-1;
1.806 + // Ensure the array of captured channels will not be modified before it has been searched
1.807 + // Because searches are bounded by the size of the array and do not involve allocating
1.808 + // or freeing memory, simply take the spinlock at the start of the operation and release at the end
1.809 + TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
1.810 + r=FindCapturedChanById(capturedChan, chanIndex);
1.811 + if((chanIndex < 0)||(r == KErrNotFound))
1.812 + r=KErrArgument;
1.813 + else
1.814 + aSlaveChanPtr = (DIicBusChannelSlave*)(iCapturedChannels[chanIndex].iChanPtr);
1.815 + __SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
1.816 +
1.817 + __ASSERT_DEBUG(aSlaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
1.818 + return r;
1.819 + }
1.820 +
1.821 +
1.822 +TInt DIicBusController::ReleaseChannel(TInt aChannelId)
1.823 + {
1.824 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::ReleaseChannel, channelID = 0x%x \n",aChannelId));
1.825 + TInt r = KErrNone;
1.826 + DIicBusChannel* chanPtr = NULL;
1.827 +
1.828 + // Get the pointer to the Slave Channel
1.829 + DIicBusChannelSlave* slaveChanPtr = NULL;
1.830 + if((r = GetSlaveChanPtr(aChannelId, slaveChanPtr)) != KErrNone)
1.831 + return r;
1.832 +
1.833 + DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
1.834 + searchChannel.SetChannelNumber(slaveChanPtr->ChannelNumber());
1.835 +
1.836 + TInt dumIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
1.837 + if(dumIndex < 0)
1.838 + {
1.839 + return KErrNotFound;
1.840 + }
1.841 + chanPtr = iChannelArray[dumIndex];
1.842 +
1.843 + __ASSERT_DEBUG(chanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
1.844 +
1.845 + //if it is the masterslave channel, then call the masterslave's RelaseChannel
1.846 + // which will call the slave channel's ReleaseChannel internally
1.847 + if(chanPtr->ChannelType() == DIicBusChannel::EMasterSlave)
1.848 + r = ((DIicBusChannelMasterSlave*)chanPtr)->ReleaseChannel();
1.849 + else // Call the slave only ReleaseChannel
1.850 + r = slaveChanPtr->ReleaseChannel();
1.851 +
1.852 + // In either case de-install the captured slave channel
1.853 + if(r == KErrNone)
1.854 + {
1.855 + r = DeInstallCapturedChannel(aChannelId, slaveChanPtr);
1.856 + }
1.857 +
1.858 + // No need to unset iController - there is only one IIC Controller
1.859 + return r;
1.860 + }
1.861 +
1.862 +
1.863 +TInt DIicBusController::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
1.864 + {
1.865 + __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));
1.866 +
1.867 + // Acquire the pointer to the Slave Channel
1.868 + DIicBusChannelSlave* slaveChanPtr = NULL;
1.869 + TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
1.870 + if(r != KErrNone)
1.871 + {
1.872 + return r;
1.873 + }
1.874 +
1.875 + // Instigate the channel functionality
1.876 + return(slaveChanPtr->RegisterRxBuffer(aRxBuffer,aBufGranularity,aNumWords,aOffset));
1.877 + }
1.878 +
1.879 +TInt DIicBusController::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
1.880 + {
1.881 + __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));
1.882 +
1.883 + // Acquire the pointer to the Slave Channel
1.884 + DIicBusChannelSlave* slaveChanPtr = NULL;
1.885 + TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
1.886 + if(r != KErrNone)
1.887 + {
1.888 + return r;
1.889 + }
1.890 +
1.891 + // Instigate the channel functionality
1.892 + return (slaveChanPtr->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset));
1.893 + }
1.894 +
1.895 +
1.896 +TInt DIicBusController::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
1.897 + {
1.898 + __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::SetNotificationTrigger - for aChannelId=0x%x, aTrigger=0x%x\n",aChannelId,aTrigger));
1.899 + // Acquire the pointer to the Slave Channel
1.900 + DIicBusChannelSlave* slaveChanPtr = NULL;
1.901 + TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
1.902 + if( r != KErrNone)
1.903 + {
1.904 + return r;
1.905 + }
1.906 +
1.907 + // Instigate the channel functionality
1.908 + return(slaveChanPtr->SetNotificationTrigger(aTrigger));
1.909 + }
1.910 +
1.911 +
1.912 +TInt DIicBusController::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
1.913 + {
1.914 +// The IIC controller and channel classes are generic, and can serve many differing client and
1.915 +// bus implementations. If a client and bus make use of specific functionality that is not
1.916 +// common to other bus types, it makes sense to provide only the minimum-required support in the
1.917 +// generic code. Here, the channel identifier is checked but all other parameters are passed
1.918 +// directly to the bus implementation channel for processing; if the channel does not provide
1.919 +// StaticExtension implementation, the generic DIicBusChannel::StaticExtension method is invoked.
1.920 +
1.921 +#ifdef IIC_INSTRUMENTATION_MACRO
1.922 + if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
1.923 + {
1.924 + IIC_MSSTATEXT_START_PIL_TRACE
1.925 + }
1.926 + else if((aFunction & KControlIoMask) == KMasterControlIo)
1.927 + {
1.928 + IIC_MSTATEXT_START_PIL_TRACE
1.929 + }
1.930 + else if((aFunction & KControlIoMask) == KSlaveControlIo)
1.931 + {
1.932 + IIC_SSTATEXT_START_PIL_TRACE
1.933 + }
1.934 +// else - Unexpected value - just pass silently to the PSL ...
1.935 +#endif
1.936 +
1.937 + // Get the channel
1.938 + TInt dumInt = 0;
1.939 + DIicBusChannel* chanPtr = NULL;
1.940 + // Can only read the channel array if it is not currently being modified
1.941 + TInt r = GetChanReadAccess();
1.942 + if(r == KErrNone)
1.943 + {
1.944 + r = GetChanPtr(aId, dumInt, chanPtr);
1.945 + if(r == KErrNone)
1.946 + {
1.947 + if(!chanPtr)
1.948 + {
1.949 + r = KErrArgument;
1.950 + }
1.951 + else
1.952 + {
1.953 + r = chanPtr->StaticExtension(aFunction, aParam1, aParam2);
1.954 + }
1.955 + }
1.956 + }
1.957 +
1.958 +#ifdef IIC_INSTRUMENTATION_MACRO
1.959 + if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
1.960 + {
1.961 + IIC_MSSTATEXT_START_PIL_TRACE
1.962 + }
1.963 + else if((aFunction & KControlIoMask) == KMasterControlIo)
1.964 + {
1.965 + IIC_MSTATEXT_START_PIL_TRACE
1.966 + }
1.967 + else if((aFunction & KControlIoMask) == KSlaveControlIo)
1.968 + {
1.969 + IIC_SSTATEXT_START_PIL_TRACE
1.970 + }
1.971 +// else ... do nothing
1.972 +#endif
1.973 + FreeChanReadAccess();
1.974 + return r;
1.975 + }
1.976 +
1.977 +
1.978 +#ifdef _DEBUG
1.979 +
1.980 +void DIicBusController::DumpCapturedChannels()
1.981 + {
1.982 + // Print iCapturedChannels ...
1.983 + TInt count=0;
1.984 + TInt i=0;
1.985 + TCapturedChannel emptyChan;
1.986 + for(;i<KMaxNumCapturedChannels;++i)
1.987 + {
1.988 + if(iCapturedChannels[i] == emptyChan)
1.989 + continue;
1.990 + ++count;
1.991 + }
1.992 +
1.993 + i = 0;
1.994 + __KTRACE_OPT(KIIC, Kern::Printf(" - Count gave %d\n",count));
1.995 + for(;i<KMaxNumCapturedChannels;++i)
1.996 + {
1.997 + if(iCapturedChannels[i] == emptyChan)
1.998 + continue;
1.999 + DIicBusChannel* ptr=(DIicBusChannel*)(iCapturedChannels[i]).iChanPtr;
1.1000 + __KTRACE_OPT(KIIC, Kern::Printf(" - ptr %d=0x%x\n",i,ptr));
1.1001 + ptr->StaticExtension(KCtrlIoDumpChan,0,0);
1.1002 + };
1.1003 + }
1.1004 +
1.1005 +void DIicBusController::DumpChannelArray()
1.1006 + {
1.1007 + TInt i = 0;
1.1008 + __KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::DumpChannelArray\n"));
1.1009 + __KTRACE_OPT(KIIC, Kern::Printf(" - Count gave %d\n",iChannelArray.Count()));
1.1010 + for(i=0; i<iChannelArray.Count(); i++)
1.1011 + {
1.1012 + DIicBusChannel* ptr=iChannelArray[i];
1.1013 + __KTRACE_OPT(KIIC, Kern::Printf(" - ptr %d=0x%x\n",i,ptr));
1.1014 + ptr->StaticExtension(KCtrlIoDumpChan,0,0);
1.1015 + };
1.1016 + }
1.1017 +
1.1018 +#endif
1.1019 +
1.1020 +#ifdef IIC_SIMULATED_PSL
1.1021 +TVersion DIicPdd::VersionRequired()
1.1022 + {
1.1023 + const TInt KIicMajorVersionNumber=1;
1.1024 + const TInt KIicMinorVersionNumber=0;
1.1025 + const TInt KIicBuildVersionNumber=KE32BuildVersionNumber;
1.1026 + return TVersion(KIicMajorVersionNumber,KIicMinorVersionNumber,KIicBuildVersionNumber);
1.1027 + }
1.1028 +
1.1029 +/** Factory class constructor */
1.1030 +DIicPdd::DIicPdd()
1.1031 + {
1.1032 + iVersion = DIicPdd::VersionRequired();
1.1033 + }
1.1034 +
1.1035 +DIicPdd::~DIicPdd()
1.1036 + {
1.1037 + delete TheController;
1.1038 + }
1.1039 +
1.1040 +TInt DIicPdd::Install()
1.1041 + {
1.1042 + return(SetName(&KPddName));
1.1043 + }
1.1044 +
1.1045 +/** Called by the kernel's device driver framework to create a Physical Channel. */
1.1046 +TInt DIicPdd::Create(DBase*& /*aChannel*/, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
1.1047 + {
1.1048 + return KErrNone;
1.1049 + }
1.1050 +
1.1051 +/** Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
1.1052 +TInt DIicPdd::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
1.1053 + {
1.1054 + if (!Kern::QueryVersionSupported(DIicPdd::VersionRequired(),aVer))
1.1055 + return(KErrNotSupported);
1.1056 + return KErrNone;
1.1057 + }
1.1058 +
1.1059 +/** Return the driver capabilities */
1.1060 +void DIicPdd::GetCaps(TDes8& aDes) const
1.1061 + {
1.1062 + // Create a capabilities object
1.1063 + TCaps caps;
1.1064 + caps.iVersion = iVersion;
1.1065 + // Zero the buffer
1.1066 + TInt maxLen = aDes.MaxLength();
1.1067 + aDes.FillZ(maxLen);
1.1068 + // Copy cpabilities
1.1069 + TInt size=sizeof(caps);
1.1070 + if(size>maxLen)
1.1071 + size=maxLen;
1.1072 + aDes.Copy((TUint8*)&caps,size);
1.1073 + }
1.1074 +#endif
1.1075 +
1.1076 +#ifndef IIC_SIMULATED_PSL
1.1077 +// Client interface entry point
1.1078 +DECLARE_EXTENSION_WITH_PRIORITY(KExtensionMaximumPriority-1) // highest priority after Resource Manager
1.1079 + {
1.1080 + TheController = new DIicBusController;
1.1081 + if(!TheController)
1.1082 + return KErrNoMemory;
1.1083 + TInt r=TheController->Create();
1.1084 + return r;
1.1085 + }
1.1086 +#else
1.1087 +static DIicPdd* TheIicPdd;
1.1088 +
1.1089 +DECLARE_STANDARD_PDD()
1.1090 + {
1.1091 + TheController = new DIicBusController;
1.1092 + if(!TheController)
1.1093 + return NULL;
1.1094 + TInt r = TheController->Create();
1.1095 + if(r == KErrNone)
1.1096 + {
1.1097 + TheIicPdd = new DIicPdd;
1.1098 + if(TheIicPdd)
1.1099 + return TheIicPdd;
1.1100 + }
1.1101 +
1.1102 + delete TheController;
1.1103 + return NULL;
1.1104 + }
1.1105 +#endif
1.1106 +
1.1107 +
1.1108 +