Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\drivers\iic.cpp
15 // IIC Controller and public API Implementation
18 #include <drivers/iic.h>
19 #include <drivers/iic_channel.h>
22 #ifdef IIC_INSTRUMENTATION_MACRO
23 #include <drivers/iic_trace.h>
26 // Global Controller pointer
27 static DIicBusController* TheController = NULL;
30 // Implementation of generic IicBus API for client interface
32 EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
34 #ifdef IIC_INSTRUMENTATION_MACRO
35 IIC_MQTRANSSYNC_START_PIL_TRACE;
37 TInt r=TheController->QueueTransaction(aBusId, aTransaction);
39 #ifdef IIC_INSTRUMENTATION_MACRO
40 IIC_MQTRANSSYNC_END_PIL_TRACE;
45 EXPORT_C TInt IicBus::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
47 #ifdef IIC_INSTRUMENTATION_MACRO
48 IIC_MQTRANSASYNC_START_PIL_TRACE;
50 TInt r=TheController->QueueTransaction(aBusId, aTransaction, aCallback);
52 #ifdef IIC_INSTRUMENTATION_MACRO
53 IIC_MQTRANSASYNC_END_PIL_TRACE;
58 EXPORT_C TInt IicBus::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
60 #ifdef IIC_INSTRUMENTATION_MACRO
61 IIC_MCANCELTRANS_START_PIL_TRACE;
63 TInt r=TheController->CancelTransaction(aBusId, aTransaction);
65 #ifdef IIC_INSTRUMENTATION_MACRO
66 IIC_MCANCELTRANS_END_PIL_TRACE;
71 EXPORT_C TInt IicBus::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
73 #ifdef IIC_INSTRUMENTATION_MACRO
76 IIC_SCAPTCHANSYNC_START_PIL_TRACE;
80 IIC_SCAPTCHANASYNC_START_PIL_TRACE;
83 TInt r=TheController->CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
85 #ifdef IIC_INSTRUMENTATION_MACRO
88 IIC_SCAPTCHANSYNC_END_PIL_TRACE;
94 EXPORT_C TInt IicBus::ReleaseChannel(TInt aChannelId)
96 #ifdef IIC_INSTRUMENTATION_MACRO
97 IIC_SRELCHAN_START_PIL_TRACE;
99 TInt r=TheController->ReleaseChannel(aChannelId);
101 #ifdef IIC_INSTRUMENTATION_MACRO
102 IIC_SRELCHAN_END_PIL_TRACE;
107 EXPORT_C TInt IicBus::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
109 #ifdef IIC_INSTRUMENTATION_MACRO
110 IIC_SREGRXBUF_START_PIL_TRACE;
112 TInt r=TheController->RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
114 #ifdef IIC_INSTRUMENTATION_MACRO
115 IIC_SREGRXBUF_END_PIL_TRACE;
120 EXPORT_C TInt IicBus::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
122 #ifdef IIC_INSTRUMENTATION_MACRO
123 IIC_SREGTXBUF_START_PIL_TRACE;
125 TInt r=TheController->RegisterTxBuffer(aChannelId, aTxBuffer, aBufGranularity, aNumWords, aOffset);
127 #ifdef IIC_INSTRUMENTATION_MACRO
128 IIC_SREGTXBUF_END_PIL_TRACE;
133 EXPORT_C TInt IicBus::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
135 #ifdef IIC_INSTRUMENTATION_MACRO
136 IIC_SNOTIFTRIG_START_PIL_TRACE;
138 TInt r=TheController->SetNotificationTrigger(aChannelId, aTrigger);
140 #ifdef IIC_INSTRUMENTATION_MACRO
141 IIC_SNOTIFTRIG_END_PIL_TRACE;
146 EXPORT_C TInt IicBus::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
148 return(TheController->StaticExtension(aId, aFunction, aParam1, aParam2));
156 // auxiliary function for ordering entries in the array of channels
157 TInt DIicBusController::OrderEntries(const DIicBusChannel& aMatch, const DIicBusChannel& aEntry)
159 TUint8 l=(TUint8)aMatch.ChannelNumber();
160 TUint8 r=(TUint8)aEntry.ChannelNumber();
169 // global ordering object to be passed to RPointerArray InsertInOrderXXX and FindInOrder
170 TLinearOrder<DIicBusChannel> EntryOrder(DIicBusController::OrderEntries);
172 // Implementation for DIicBusController
175 TInt DIicBusController::Create()
178 iChanLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2); // Semi-arbitrary, low priority value
179 iCaptLock = new TSpinLock(TSpinLock::EOrderGenericIrqLow2); // Semi-arbitrary, low priority value
180 if((iChanLock == NULL)||(iCaptLock == NULL))
189 DIicBusController::~DIicBusController()
191 #ifdef IIC_SIMULATED_PSL
192 for(TInt i=0; i<iChannelArray.Count(); i++)
194 DIicBusChannel* ptr=iChannelArray[i];
195 // Remove the channel from the array
196 iChannelArray.Remove(i);
197 // Delete the channel object
201 iChannelArray.Reset();
207 TInt DIicBusController::GetChanWriteAccess()
209 // Can only have one insertion or removal active at any one time
210 // Can not perform an insertion or removal while a read is in progress
211 // If either of the two above conditions exist, return KErrInUse
212 // Otherwise, set the flag to indicate that a write is in progress
213 // and return KErrNone.
215 chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
216 if(iChanRwFlags != 0)
218 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
221 iChanRwFlags |= EWriteInProgress;
222 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
226 void DIicBusController::FreeChanWriteAccess()
228 // If an insertion or removal is in progress, no other modifying operation
229 // can be active. Reads are also not permitted - so iChanRwFlags can only be
231 __ASSERT_DEBUG(iChanRwFlags == EWriteInProgress, Kern::Fault(KIicPanic,__LINE__));
233 chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
234 iChanRwFlags &= ~EWriteInProgress;
235 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
238 TInt DIicBusController::GetChanReadAccess()
240 // No reads are permitted while an insertion or removal is in progress
241 // If one of the above operations is in progress return KErrInUse
242 // Can have several concurrent reads at any one time - so increment
243 // the count of such operations as well as ensuring the flag is set to indicate
244 // a read is in progress
246 chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
247 if(iChanRwFlags == EWriteInProgress)
249 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
252 __ASSERT_DEBUG(iChanRdCount!=0xFFFFFFFF, Kern::Fault(KIicPanic,__LINE__)); // Overflow
254 iChanRwFlags |= EReadInProgress;
255 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
259 void DIicBusController::FreeChanReadAccess()
261 // No insertions or removals are permitted while a read is in progress
262 // so iChanRwFlags can only be EReadInProgress
263 // Multiple reads can be in progress concurrently, so the count must be decremented
265 chanIntState=__SPIN_LOCK_IRQSAVE(*iChanLock);
266 __ASSERT_DEBUG(iChanRwFlags == EReadInProgress, Kern::Fault(KIicPanic,__LINE__));
267 __ASSERT_DEBUG(iChanRdCount>0, Kern::Fault(KIicPanic,__LINE__));
269 if(iChanRdCount == 0)
270 iChanRwFlags &= ~EReadInProgress;
271 __SPIN_UNLOCK_IRQRESTORE(*iChanLock,chanIntState);
274 TInt DIicBusController::RequestTypeSupported(const TInt aBusId, DIicBusChannelMaster* const aChannel)
277 reqBusType = GET_BUS_TYPE(aBusId);
278 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RequestTypeSupported, BusType=0x%x\n", reqBusType));
280 if(reqBusType != aChannel->BusType())
282 return KErrNotSupported;
289 EXPORT_C TInt DIicBusController::RegisterChannels(DIicBusChannel** aListChannels, TInt aNumberChannels)
291 // To be used by Channel implementations to register a list of supported channels
292 __KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::RegisterChannels, aListChannels=0x%x, aNumberChannels=%d\n",aListChannels,aNumberChannels));
293 __ASSERT_DEBUG(aListChannels!=NULL, Kern::Fault(KIicPanic,__LINE__));
295 RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
297 #ifdef IIC_INSTRUMENTATION_MACRO
298 IIC_REGISTERCHANS_START_PIL_TRACE;
300 // Get access to the channel pointer array - exit if it is currently being modfied
302 if((r=TheController->GetChanWriteAccess()) == KErrNone)
305 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On entry, iChannelArray ...\n"));
306 TheController->DumpChannelArray();
308 // Loop for aNumberChannels and write directly to the channel array
309 DIicBusChannel** chanIterator = aListChannels;
310 for(TInt iteration = 0; iteration < aNumberChannels; ++iteration, ++chanIterator)
312 DIicBusChannel* chanPtr = *chanIterator;
313 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - adding channel number %d\n",chanPtr->ChannelNumber()));
314 TInt r = chanArray->InsertInOrder(chanPtr,EntryOrder);
320 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::RegisterChannels - On exit, iChannelArray ...\n"));
321 TheController->DumpChannelArray();
323 TheController->FreeChanWriteAccess();
327 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanWriteAccess returned %d\n",r));
330 #ifdef IIC_INSTRUMENTATION_MACRO
331 IIC_REGISTERCHANS_END_PIL_TRACE;
337 EXPORT_C TInt DIicBusController::DeRegisterChannel(DIicBusChannel* aChannel)
339 // To be used by Channel implementations to deregister a channel
340 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel, aChannel=0x%x\n",aChannel));
344 RPointerArray<DIicBusChannel>* chanArray = TheController->ChannelArray();
346 #ifdef IIC_INSTRUMENTATION_MACRO
347 IIC_DEREGISTERCHAN_START_PIL_TRACE;
350 // Get access to the channel pointer array - exit if it is currently unavailable
351 // Gaining write access will prevent a client of a Master Channel from instigating a new QueueTransaction
352 // (or CancelTransaction), and it will obstruct a client of a Slave Channel in CaptureChannel.
353 if((r=TheController->GetChanWriteAccess())!=KErrNone)
356 // Check channel is registered
357 TInt chanIndex = chanArray->FindInOrder(aChannel,EntryOrder);
360 TheController->FreeChanWriteAccess();
365 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On entry, iChannelArray ...\n"));
366 TheController->DumpChannelArray();
369 // Remove the channel from the array
370 // Note that this does not delete the channel object
371 chanArray->Remove(chanIndex);
374 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeRegisterChannel - On exit, iChannelArray ...\n"));
375 TheController->DumpChannelArray();
377 TheController->FreeChanWriteAccess();
379 #ifdef IIC_INSTRUMENTATION_MACRO
380 IIC_DEREGISTERCHAN_END_PIL_TRACE;
385 TInt DIicBusController::FindCapturedChanById(TCapturedChannel aCapturedChan, TInt& aIndex)
391 if(iCapturedChannels[index].iChannelId == aCapturedChan.iChannelId)
397 } while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
401 TInt DIicBusController::FindCapturedChan(TCapturedChannel aCapturedChan, TInt& aIndex)
407 if(iCapturedChannels[index] == aCapturedChan)
413 } while ((index < KMaxNumCapturedChannels)&&(r == KErrNotFound));
417 TInt DIicBusController::InsertCaptChanInArray(TCapturedChannel aCapturedChan)
419 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InsertCaptChanInArray \n"));
420 // Ensure the channel hasn't already been inserted in the array
421 // If found, fault the Kernel
423 TInt r=FindCapturedChan(aCapturedChan,dumInt);
424 __ASSERT_DEBUG(r!=KErrNone, Kern::Fault(KIicPanic,__LINE__));
426 // Loop the array and insert in the first available slot
427 // If no slots are available return KErrNotReady
429 TCapturedChannel emptyChan;
430 for(;index<KMaxNumCapturedChannels;++index)
432 if(iCapturedChannels[index] == emptyChan)
435 iCapturedChannels[index]=aCapturedChan;
439 if(index>=KMaxNumCapturedChannels)
444 TInt DIicBusController::RemoveCaptChanFromArray(TCapturedChannel aCapturedChan)
446 // Remove the entry from the array
447 // If the entry is not present return KErrArgument
449 TInt r=FindCapturedChan(aCapturedChan,index);
450 if((r!=KErrNone)||(index>=KMaxNumCapturedChannels))
452 iCapturedChannels[index].iChanPtr=NULL;
453 iCapturedChannels[index].iChannelId=0;
458 TInt DIicBusController::InstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
461 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On entry, iCapturedChannels ...\n"));
462 DumpCapturedChannels();
465 TCapturedChannel capturedChan((TInt)aChannelId,(DIicBusChannelSlave*)aChanPtr);
466 // Because insertions are bounded by the size of the array and do not involve allocating
467 // or freeing memory, simply take the spinlock at the start of the operation and release at the end
468 TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
469 r=InsertCaptChanInArray(capturedChan);
470 __SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
475 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::InstallCapturedChannel - On exit, iCapturedChannels ...\n"));
476 DumpCapturedChannels();
481 TInt DIicBusController::DeInstallCapturedChannel(const TInt aChannelId, const DIicBusChannelSlave* aChanPtr)
484 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On entry, iCapturedChannels ...\n"));
485 DumpCapturedChannels();
488 TCapturedChannel capturedChan((TInt) aChannelId, (DIicBusChannelSlave*) aChanPtr);
489 // Because removals are bounded by the size of the array and do not involve allocating
490 // or freeing memory, simply take the spinlock at the start of the operation and release at the end
491 TInt captIntState = __SPIN_LOCK_IRQSAVE(*iCaptLock);
492 r = RemoveCaptChanFromArray(capturedChan);
493 __SPIN_UNLOCK_IRQRESTORE(*iCaptLock, captIntState);
498 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::DeInstallCapturedChannel - On exit, iCapturedChannels ...\n"));
499 DumpCapturedChannels();
505 TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
507 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
513 // Get a pointer to the channel
515 DIicBusChannel* chanPtr = NULL;
516 // Can only read the channel array if it is not currently being modified
517 TInt r = GetChanReadAccess();
522 r = GetChanPtr(aBusId, dumInt, chanPtr);
531 switch(chanPtr->ChannelType())
533 // QueueTransaction requests are only supported by channels in Master mode.
534 case DIicBusChannel::ESlave:
536 r = KErrNotSupported;
539 // If the request is supported by the Master channel, send it to the channel for processing in its thread
540 case DIicBusChannel::EMasterSlave:
542 r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
545 aTransaction->iBusId = aBusId;
546 r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction));
550 case DIicBusChannel::EMaster:
552 r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
555 aTransaction->iBusId = aBusId;
556 r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction));
567 FreeChanReadAccess();
571 TInt DIicBusController::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback* aCallback)
573 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::QueueTransaction, aBusId=0x%x,aTransaction=0x%x,aCallback=0x%x\n",aBusId,aTransaction,aCallback));
574 if(!aTransaction || !aCallback)
579 // Get a pointer to the channel
581 DIicBusChannel* chanPtr = NULL;
582 // Can only read the channel array if it is not currently being modified
583 TInt r = GetChanReadAccess();
586 r = GetChanPtr(aBusId, dumInt, chanPtr);
595 switch(chanPtr->ChannelType())
597 // QueueTransaction requests are only supported by channels in Master mode.
598 case DIicBusChannel::ESlave:
600 r = KErrNotSupported;
603 // If the request is supported by the Master channel, send it to the channel for processing in its thread
604 case DIicBusChannel::EMasterSlave:
606 r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
609 aTransaction->iBusId = aBusId;
610 r = (((DIicBusChannelMasterSlave*) chanPtr)->QueueTransaction(aTransaction, aCallback));
614 case DIicBusChannel::EMaster:
616 r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
619 aTransaction->iBusId = aBusId;
620 r = (((DIicBusChannelMaster*) chanPtr)->QueueTransaction(aTransaction, aCallback));
632 FreeChanReadAccess();
637 TInt DIicBusController::GetChanPtr(const TInt aBusId, TInt &aIndex, DIicBusChannel*& aChan)
639 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, aBusId=0x%x\n",aBusId));
642 chanId = GET_CHAN_NUM(aBusId);
644 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanId=0x%x\n", chanId));
645 DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
646 searchChannel.SetChannelNumber((TInt8)chanId);
648 TInt r = KErrNotFound;
649 aIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
652 aChan = iChannelArray[aIndex];
656 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::GetChanPtr, chanPtr=0x%x, index=%d\n", aChan, aIndex));
661 TInt DIicBusController::CancelTransaction(TInt aBusId, TIicBusTransaction* aTransaction)
663 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::CancelTransaction, aBusId=0x%x,aTransaction=0x%x\n", aBusId, aTransaction));
671 DIicBusChannel* chanPtr = NULL;
673 // Can only read the channel array if it is not currently being modified
674 TInt r = GetChanReadAccess();
677 r = GetChanPtr(aBusId, dumInt, chanPtr);
686 // QueueTransaction requests are only supported by channels in Master mode.
687 switch(chanPtr->ChannelType())
689 case DIicBusChannel::ESlave:
691 r = KErrNotSupported;
694 case DIicBusChannel::EMasterSlave:
696 r = RequestTypeSupported(aBusId, ((DIicBusChannelMasterSlave*)chanPtr)->iMasterChannel);
699 r = (((DIicBusChannelMasterSlave*) chanPtr)->CancelTransaction(aTransaction));
703 case DIicBusChannel::EMaster:
705 r = RequestTypeSupported(aBusId, (DIicBusChannelMaster*)chanPtr);
708 r = (((DIicBusChannelMaster*) chanPtr)->CancelTransaction(aTransaction));
720 FreeChanReadAccess();
725 TInt DIicBusController::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
727 // Check that that aCallback!=NULL and aConfigHdr!=NULL - if not, return KErrArgument
728 if(!aCallback || !aConfigHdr)
735 DIicBusChannel* chanPtr = NULL;
737 // Can only read the channel array if it is not currently being modified
738 TInt r = GetChanReadAccess();
741 r = GetChanPtr(aBusId, chanIndex, chanPtr);
750 DIicBusChannelSlave* slaveChanPtr = NULL;
751 switch(chanPtr->ChannelType())
753 // CaptureChannel requests are only supported by channels in Slave mode.
754 case DIicBusChannel::EMaster:
756 r = KErrNotSupported;
759 case DIicBusChannel::EMasterSlave:
761 slaveChanPtr = ((DIicBusChannelMasterSlave*) chanPtr)->iSlaveChannel;
762 __ASSERT_DEBUG(slaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__)); // MasterSlave channel should have a valid Slave channel
763 // Send the request to the channel
764 slaveChanPtr->iController = this;
765 r = ((DIicBusChannelMasterSlave*) chanPtr)->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
768 case DIicBusChannel::ESlave:
770 slaveChanPtr = (DIicBusChannelSlave*) chanPtr; // chanPtr is non-NULL
771 // Send the request to the channel
772 slaveChanPtr->iController = this;
773 r = (slaveChanPtr->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch));
781 // For synchronous capture, if successful then install the channel
782 if(r == KErrNone && slaveChanPtr)
786 InstallCapturedChannel(aChannelId, slaveChanPtr);
792 FreeChanReadAccess();
797 TInt DIicBusController::GetSlaveChanPtr(TInt aChannelId, DIicBusChannelSlave*& aSlaveChanPtr)
800 // Check that the channelID is recognised
801 TCapturedChannel capturedChan(aChannelId,NULL);
803 // Ensure the array of captured channels will not be modified before it has been searched
804 // Because searches are bounded by the size of the array and do not involve allocating
805 // or freeing memory, simply take the spinlock at the start of the operation and release at the end
806 TInt captIntState=__SPIN_LOCK_IRQSAVE(*iCaptLock);
807 r=FindCapturedChanById(capturedChan, chanIndex);
808 if((chanIndex < 0)||(r == KErrNotFound))
811 aSlaveChanPtr = (DIicBusChannelSlave*)(iCapturedChannels[chanIndex].iChanPtr);
812 __SPIN_UNLOCK_IRQRESTORE(*iCaptLock,captIntState);
814 __ASSERT_DEBUG(aSlaveChanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
819 TInt DIicBusController::ReleaseChannel(TInt aChannelId)
821 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::ReleaseChannel, channelID = 0x%x \n",aChannelId));
823 DIicBusChannel* chanPtr = NULL;
825 // Get the pointer to the Slave Channel
826 DIicBusChannelSlave* slaveChanPtr = NULL;
827 if((r = GetSlaveChanPtr(aChannelId, slaveChanPtr)) != KErrNone)
830 DIicBusChannelSearcher searchChannel(DIicBusChannel::EMasterSlave, DIicBusChannel::ESccb, DIicBusChannel::EFullDuplex);
831 searchChannel.SetChannelNumber(slaveChanPtr->ChannelNumber());
833 TInt dumIndex = iChannelArray.FindInOrder(&searchChannel, EntryOrder);
838 chanPtr = iChannelArray[dumIndex];
840 __ASSERT_DEBUG(chanPtr!=NULL, Kern::Fault(KIicPanic,__LINE__));
842 //if it is the masterslave channel, then call the masterslave's RelaseChannel
843 // which will call the slave channel's ReleaseChannel internally
844 if(chanPtr->ChannelType() == DIicBusChannel::EMasterSlave)
845 r = ((DIicBusChannelMasterSlave*)chanPtr)->ReleaseChannel();
846 else // Call the slave only ReleaseChannel
847 r = slaveChanPtr->ReleaseChannel();
849 // In either case de-install the captured slave channel
852 r = DeInstallCapturedChannel(aChannelId, slaveChanPtr);
855 // No need to unset iController - there is only one IIC Controller
860 TInt DIicBusController::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
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));
864 // Acquire the pointer to the Slave Channel
865 DIicBusChannelSlave* slaveChanPtr = NULL;
866 TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
872 // Instigate the channel functionality
873 return(slaveChanPtr->RegisterRxBuffer(aRxBuffer,aBufGranularity,aNumWords,aOffset));
876 TInt DIicBusController::RegisterTxBuffer(TInt aChannelId, TPtr8 aTxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
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));
880 // Acquire the pointer to the Slave Channel
881 DIicBusChannelSlave* slaveChanPtr = NULL;
882 TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
888 // Instigate the channel functionality
889 return (slaveChanPtr->RegisterTxBuffer(aTxBuffer, aBufGranularity, aNumWords, aOffset));
893 TInt DIicBusController::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
895 __KTRACE_OPT(KIIC, Kern::Printf("DIicBusController::SetNotificationTrigger - for aChannelId=0x%x, aTrigger=0x%x\n",aChannelId,aTrigger));
896 // Acquire the pointer to the Slave Channel
897 DIicBusChannelSlave* slaveChanPtr = NULL;
898 TInt r = GetSlaveChanPtr(aChannelId, slaveChanPtr);
904 // Instigate the channel functionality
905 return(slaveChanPtr->SetNotificationTrigger(aTrigger));
909 TInt DIicBusController::StaticExtension(TUint aId, TUint aFunction, TAny* aParam1, TAny* aParam2)
911 // The IIC controller and channel classes are generic, and can serve many differing client and
912 // bus implementations. If a client and bus make use of specific functionality that is not
913 // common to other bus types, it makes sense to provide only the minimum-required support in the
914 // generic code. Here, the channel identifier is checked but all other parameters are passed
915 // directly to the bus implementation channel for processing; if the channel does not provide
916 // StaticExtension implementation, the generic DIicBusChannel::StaticExtension method is invoked.
918 #ifdef IIC_INSTRUMENTATION_MACRO
919 if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
921 IIC_MSSTATEXT_START_PIL_TRACE
923 else if((aFunction & KControlIoMask) == KMasterControlIo)
925 IIC_MSTATEXT_START_PIL_TRACE
927 else if((aFunction & KControlIoMask) == KSlaveControlIo)
929 IIC_SSTATEXT_START_PIL_TRACE
931 // else - Unexpected value - just pass silently to the PSL ...
936 DIicBusChannel* chanPtr = NULL;
937 // Can only read the channel array if it is not currently being modified
938 TInt r = GetChanReadAccess();
941 r = GetChanPtr(aId, dumInt, chanPtr);
950 r = chanPtr->StaticExtension(aFunction, aParam1, aParam2);
955 #ifdef IIC_INSTRUMENTATION_MACRO
956 if((aFunction & KControlIoMask) == KMasterSlaveControlIo)
958 IIC_MSSTATEXT_START_PIL_TRACE
960 else if((aFunction & KControlIoMask) == KMasterControlIo)
962 IIC_MSTATEXT_START_PIL_TRACE
964 else if((aFunction & KControlIoMask) == KSlaveControlIo)
966 IIC_SSTATEXT_START_PIL_TRACE
968 // else ... do nothing
970 FreeChanReadAccess();
977 void DIicBusController::DumpCapturedChannels()
979 // Print iCapturedChannels ...
982 TCapturedChannel emptyChan;
983 for(;i<KMaxNumCapturedChannels;++i)
985 if(iCapturedChannels[i] == emptyChan)
991 __KTRACE_OPT(KIIC, Kern::Printf(" - Count gave %d\n",count));
992 for(;i<KMaxNumCapturedChannels;++i)
994 if(iCapturedChannels[i] == emptyChan)
996 DIicBusChannel* ptr=(DIicBusChannel*)(iCapturedChannels[i]).iChanPtr;
997 __KTRACE_OPT(KIIC, Kern::Printf(" - ptr %d=0x%x\n",i,ptr));
998 ptr->StaticExtension(KCtrlIoDumpChan,0,0);
1002 void DIicBusController::DumpChannelArray()
1005 __KTRACE_OPT(KIIC, Kern::Printf("\nDIicBusController::DumpChannelArray\n"));
1006 __KTRACE_OPT(KIIC, Kern::Printf(" - Count gave %d\n",iChannelArray.Count()));
1007 for(i=0; i<iChannelArray.Count(); i++)
1009 DIicBusChannel* ptr=iChannelArray[i];
1010 __KTRACE_OPT(KIIC, Kern::Printf(" - ptr %d=0x%x\n",i,ptr));
1011 ptr->StaticExtension(KCtrlIoDumpChan,0,0);
1017 #ifdef IIC_SIMULATED_PSL
1018 TVersion DIicPdd::VersionRequired()
1020 const TInt KIicMajorVersionNumber=1;
1021 const TInt KIicMinorVersionNumber=0;
1022 const TInt KIicBuildVersionNumber=KE32BuildVersionNumber;
1023 return TVersion(KIicMajorVersionNumber,KIicMinorVersionNumber,KIicBuildVersionNumber);
1026 /** Factory class constructor */
1029 iVersion = DIicPdd::VersionRequired();
1034 delete TheController;
1037 TInt DIicPdd::Install()
1039 return(SetName(&KPddName));
1042 /** Called by the kernel's device driver framework to create a Physical Channel. */
1043 TInt DIicPdd::Create(DBase*& /*aChannel*/, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
1048 /** Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
1049 TInt DIicPdd::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
1051 if (!Kern::QueryVersionSupported(DIicPdd::VersionRequired(),aVer))
1052 return(KErrNotSupported);
1056 /** Return the driver capabilities */
1057 void DIicPdd::GetCaps(TDes8& aDes) const
1059 // Create a capabilities object
1061 caps.iVersion = iVersion;
1063 TInt maxLen = aDes.MaxLength();
1066 TInt size=sizeof(caps);
1069 aDes.Copy((TUint8*)&caps,size);
1073 #ifndef IIC_SIMULATED_PSL
1074 // Client interface entry point
1075 DECLARE_EXTENSION_WITH_PRIORITY(KExtensionMaximumPriority-1) // highest priority after Resource Manager
1077 TheController = new DIicBusController;
1079 return KErrNoMemory;
1080 TInt r=TheController->Create();
1084 static DIicPdd* TheIicPdd;
1086 DECLARE_STANDARD_PDD()
1088 TheController = new DIicBusController;
1091 TInt r = TheController->Create();
1094 TheIicPdd = new DIicPdd;
1099 delete TheController;