18 |
18 |
19 #ifdef IIC_INSTRUMENTATION_MACRO |
19 #ifdef IIC_INSTRUMENTATION_MACRO |
20 #include <drivers/iic_trace.h> |
20 #include <drivers/iic_trace.h> |
21 #endif |
21 #endif |
22 |
22 |
23 |
23 #ifndef STANDALONE_CHANNEL |
24 #if defined(MASTER_MODE) && !defined(SLAVE_MODE) |
24 #if defined(MASTER_MODE) && !defined(SLAVE_MODE) |
25 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster}; |
25 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::EMaster, DIicBusChannel::EMaster}; |
26 #elif defined(MASTER_MODE) && defined(SLAVE_MODE) |
26 #elif defined(MASTER_MODE) && defined(SLAVE_MODE) |
27 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave}; |
27 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::EMaster, DIicBusChannel::ESlave, DIicBusChannel::EMasterSlave}; |
28 #else |
28 #else |
29 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave}; |
29 const TInt KChannelTypeArray[NUM_CHANNELS] = {DIicBusChannel::ESlave, DIicBusChannel::ESlave, DIicBusChannel::ESlave}; |
30 #endif |
30 #endif |
31 #define CHANNEL_TYPE(n) (KChannelTypeArray[n]) |
31 #define CHANNEL_TYPE(n) (KChannelTypeArray[n]) |
32 #define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex) |
32 #define CHANNEL_DUPLEX(n) (DIicBusChannel::EHalfDuplex) |
|
33 #endif/*STANDALONE_CHANNEL*/ |
33 |
34 |
34 #ifdef STANDALONE_CHANNEL |
35 #ifdef STANDALONE_CHANNEL |
35 _LIT(KPddNameI2c,"i2c_ctrless.pdd"); |
36 _LIT(KPddNameI2c,"i2c_ctrless.pdd"); |
36 #else |
37 #else |
37 _LIT(KPddNameI2c,"i2c.pdd"); |
38 _LIT(KPddNameI2c,"i2c.pdd"); |
44 I2C_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNum)); |
45 I2C_PRINT(("I2C AssignChanNum - on entry, iBaseChanNum = 0x%x\n",iBaseChanNum)); |
45 return iBaseChanNum++; // Arbitrary, for illustration |
46 return iBaseChanNum++; // Arbitrary, for illustration |
46 } |
47 } |
47 #endif/*STANDALONE_CHANNEL*/ |
48 #endif/*STANDALONE_CHANNEL*/ |
48 |
49 |
49 #ifdef SLAVE_MODE |
50 //Macros MASTER_MODE and SLAVE_MODE are intentionally omitted from this file |
|
51 //This is for master and slave stubs to exercise the channel class, |
|
52 //and we need these stubs for code coverage tests. |
50 LOCAL_C TInt16 AssignSlaveChanId() |
53 LOCAL_C TInt16 AssignSlaveChanId() |
51 { |
54 { |
52 static TInt16 iBaseSlaveChanId = KI2cSlaveChannelIdBase; |
55 static TInt16 iBaseSlaveChanId = KI2cSlaveChannelIdBase; |
53 I2C_PRINT(("I2C AssignSlaveChanId - on entry, iBaseSlaveChanId = 0x%x\n",iBaseSlaveChanId)); |
56 I2C_PRINT(("I2C AssignSlaveChanId - on entry, iBaseSlaveChanId = 0x%x\n",iBaseSlaveChanId)); |
54 return iBaseSlaveChanId++; // Arbitrary, for illustration |
57 return iBaseSlaveChanId++; // Arbitrary, for illustration |
55 } |
58 } |
56 #endif/*SLAVE_MODE*/ |
|
57 |
59 |
58 NONSHARABLE_CLASS(DSimulatedI2cDevice) : public DPhysicalDevice |
60 NONSHARABLE_CLASS(DSimulatedI2cDevice) : public DPhysicalDevice |
59 { |
61 { |
60 // Class to faciliate loading of the IIC classes |
62 // Class to faciliate loading of the IIC classes |
61 public: |
63 public: |
123 if(size>maxLen) |
125 if(size>maxLen) |
124 size=maxLen; |
126 size=maxLen; |
125 aDes.Copy((TUint8*)&caps,size); |
127 aDes.Copy((TUint8*)&caps,size); |
126 } |
128 } |
127 |
129 |
|
130 #ifndef STANDALONE_CHANNEL |
128 // supported channels for this implementation |
131 // supported channels for this implementation |
129 static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS]; |
132 static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS]; |
130 |
133 #endif |
131 |
134 |
132 //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY) |
135 //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY) |
133 DECLARE_STANDARD_PDD() // I2c test driver to be explicitly loaded as an LDD, not kernel extension |
136 DECLARE_STANDARD_PDD() // I2c test driver to be explicitly loaded as an LDD, not kernel extension |
134 { |
137 { |
135 #ifndef STANDALONE_CHANNEL |
138 #ifndef STANDALONE_CHANNEL |
249 TInt r=Init(); // PIL Base class initialisation |
250 TInt r=Init(); // PIL Base class initialisation |
250 r=Kern::DynamicDfcQCreate(iDynamicDfcQ,KI2cThreadPriority,KI2cThreadName); |
251 r=Kern::DynamicDfcQCreate(iDynamicDfcQ,KI2cThreadPriority,KI2cThreadName); |
251 if(r == KErrNone) |
252 if(r == KErrNone) |
252 SetDfcQ((TDfcQue*)iDynamicDfcQ); |
253 SetDfcQ((TDfcQue*)iDynamicDfcQ); |
253 DSimulatedIicBusChannelMasterI2c::SetRequestDelayed(this,EFalse); |
254 DSimulatedIicBusChannelMasterI2c::SetRequestDelayed(this,EFalse); |
|
255 //Call to base class DoCreate(not strictly necessary) |
|
256 DIicBusChannelMaster::DoCreate(); |
254 return r; |
257 return r; |
255 } |
258 } |
256 |
259 |
257 TInt DSimulatedIicBusChannelMasterI2c::CheckHdr(TDes8* aHdr) |
260 TInt DSimulatedIicBusChannelMasterI2c::CheckHdr(TDes8* aHdr) |
258 { |
261 { |
419 break; |
422 break; |
420 } |
423 } |
421 default: |
424 default: |
422 { |
425 { |
423 Kern::Printf("aFunction %d is not recognised \n",aFunction); |
426 Kern::Printf("aFunction %d is not recognised \n",aFunction); |
424 r=KErrNotSupported; |
427 //For default case call the base class method for consistent handling |
|
428 r=DIicBusChannelMaster::StaticExtension(aFunction,NULL,NULL); |
425 } |
429 } |
426 } |
430 } |
427 |
431 |
428 #ifdef IIC_INSTRUMENTATION_MACRO |
432 #ifdef IIC_INSTRUMENTATION_MACRO |
429 IIC_MSTATEXT_END_PSL_TRACE; |
433 IIC_MSTATEXT_END_PSL_TRACE; |
430 #endif |
434 #endif |
431 return r; |
435 return r; |
432 } |
436 } |
433 |
437 |
434 //#ifdef MASTER_MODE |
|
435 #endif |
|
436 |
|
437 #ifdef SLAVE_MODE |
|
438 |
|
439 void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr) |
438 void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr) |
440 { |
439 { |
441 // To support simulating an asynchronous capture operation |
440 // To support simulating an asynchronous capture operation |
442 // NOTE: this will be invoked in the context of DfcThread1 |
|
443 I2C_PRINT(("SlaveAsyncSimCallback\n")); |
441 I2C_PRINT(("SlaveAsyncSimCallback\n")); |
444 DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr; |
442 DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr; |
445 TInt r=KErrNone;// Just simulate successful capture |
443 |
446 #ifdef IIC_INSTRUMENTATION_MACRO |
444 // This will be invoked in the context of DfcThread1, so require |
447 IIC_SCAPTCHANASYNC_END_PSL_TRACE; |
445 // synchronised access to iAsyncEvent and iRxTxTrigger |
448 #endif |
446 // Use local variables to enable early release of the spin lock |
449 channel->ChanCaptureCb(r); |
447 // |
|
448 // If DfcThread1 runs on a separate core to the simulated I2C bus, the other core |
|
449 // will have updated values, and since this core may cached copies, memory access |
|
450 // should be observed. The spin lock mechanism is expected to incorpoate this. |
|
451 TInt intState=__SPIN_LOCK_IRQSAVE(channel->iEventSpinLock); |
|
452 |
|
453 TAsyncEvent asyncEvent = channel->iAsyncEvent; |
|
454 TInt rxTxTrigger = channel->iRxTxTrigger; |
|
455 channel->iAsyncEvent = ENoEvent; |
|
456 channel->iRxTxTrigger = 0; |
|
457 __SPIN_UNLOCK_IRQRESTORE(channel->iEventSpinLock,intState); |
|
458 |
|
459 switch(asyncEvent) |
|
460 { |
|
461 case (EAsyncChanCapture): |
|
462 { |
|
463 TInt r=KErrNone;// Just simulate successful capture |
|
464 #ifdef IIC_INSTRUMENTATION_MACRO |
|
465 IIC_SCAPTCHANASYNC_END_PSL_TRACE; |
|
466 #endif |
|
467 channel->ChanCaptureCb(r); |
|
468 break; |
|
469 } |
|
470 case (ERxWords): |
|
471 case (ETxWords): |
|
472 case (ERxTxWords): |
|
473 { |
|
474 channel->ChanNotifyClient(rxTxTrigger); |
|
475 break; |
|
476 } |
|
477 default: |
|
478 { |
|
479 } |
|
480 } |
450 } |
481 } |
451 |
482 |
452 #ifdef STANDALONE_CHANNEL |
483 #ifdef STANDALONE_CHANNEL |
453 EXPORT_C |
484 EXPORT_C |
454 #endif |
485 #endif |
455 DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex) |
486 DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex) |
456 : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class |
487 : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class |
457 iBlockedTrigger(0),iBlockNotification(EFalse), |
488 iBlockedTrigger(0),iBlockNotification(EFalse),iAsyncEvent(ENoEvent),iRxTxTrigger(0), |
458 iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this) |
489 iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this), |
|
490 iEventSpinLock(TSpinLock::EOrderGenericIrqHigh2) // Semi-arbitrary, high priority value (NTimer used) |
459 { |
491 { |
460 I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex)); |
492 I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex)); |
461 #ifndef STANDALONE_CHANNEL |
493 #ifndef STANDALONE_CHANNEL |
462 iChannelNumber = AssignChanNum(); |
494 iChannelNumber = AssignChanNum(); |
463 #endif |
495 #endif |
486 { |
518 { |
487 #ifdef IIC_INSTRUMENTATION_MACRO |
519 #ifdef IIC_INSTRUMENTATION_MACRO |
488 IIC_SCAPTCHANASYNC_START_PSL_TRACE; |
520 IIC_SCAPTCHANASYNC_START_PSL_TRACE; |
489 #endif |
521 #endif |
490 // To simulate an asynchronous capture operation, just set a timer to expire |
522 // To simulate an asynchronous capture operation, just set a timer to expire |
491 iSlaveTimer.OneShot(1000, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
523 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
524 iAsyncEvent = EAsyncChanCapture; |
|
525 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
526 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
492 } |
527 } |
493 else |
528 else |
494 { |
529 { |
495 #ifdef IIC_INSTRUMENTATION_MACRO |
530 #ifdef IIC_INSTRUMENTATION_MACRO |
496 IIC_SCAPTCHANSYNC_START_PSL_TRACE; |
531 IIC_SCAPTCHANSYNC_START_PSL_TRACE; |
707 } |
741 } |
708 } |
742 } |
709 if(iBlockNotification == EFalse) |
743 if(iBlockNotification == EFalse) |
710 { |
744 { |
711 // |
745 // |
712 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
746 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
713 NotifyClient(trigger); |
747 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
748 // Tx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
749 iRxTxTrigger |= trigger; |
|
750 iAsyncEvent = ERxWords; |
|
751 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
752 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
714 } |
753 } |
715 else |
754 else |
716 { |
755 { |
717 // Save the trigger value to notify when prompted. |
756 // Save the trigger value to notify when prompted. |
718 iBlockedTrigger=trigger; |
757 iBlockedTrigger=trigger; |
782 *dstPtr++=*srcPtr++; |
821 *dstPtr++=*srcPtr++; |
783 } |
822 } |
784 if(iBlockNotification == EFalse) |
823 if(iBlockNotification == EFalse) |
785 { |
824 { |
786 // |
825 // |
787 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
826 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
788 NotifyClient(trigger); |
827 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
828 // Rx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
829 iRxTxTrigger |= trigger; |
|
830 iAsyncEvent = ETxWords; |
|
831 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
832 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
|
833 // No effect if OneShot already invoked |
789 } |
834 } |
790 else |
835 else |
791 { |
836 { |
792 // Save the trigger value to notify when prompted. |
837 // Save the trigger value to notify when prompted. |
793 iBlockedTrigger=trigger; |
838 iBlockedTrigger=trigger; |
866 } |
911 } |
867 |
912 |
868 if(iBlockNotification == EFalse) |
913 if(iBlockNotification == EFalse) |
869 { |
914 { |
870 // |
915 // |
871 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
916 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
872 NotifyClient(trigger); |
917 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
918 // Rx or Tx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
919 iRxTxTrigger |= trigger; |
|
920 iAsyncEvent = ERxTxWords; |
|
921 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
922 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
873 } |
923 } |
874 else |
924 else |
875 { |
925 { |
876 // Save the trigger value to notify when prompted. |
926 // Save the trigger value to notify when prompted. |
877 iBlockedTrigger=trigger; |
927 iBlockedTrigger=trigger; |
987 } |
1037 } |
988 |
1038 |
989 default: |
1039 default: |
990 { |
1040 { |
991 Kern::Printf("aFunction %d is not recognised \n",aFunction); |
1041 Kern::Printf("aFunction %d is not recognised \n",aFunction); |
992 r=KErrNotSupported; |
1042 //For default case call the base class method for consistent handling |
|
1043 r=DIicBusChannelSlave::StaticExtension(aFunction,NULL,NULL); |
993 } |
1044 } |
994 } |
1045 } |
995 #ifdef IIC_INSTRUMENTATION_MACRO |
1046 #ifdef IIC_INSTRUMENTATION_MACRO |
996 IIC_SSTATEXT_END_PSL_TRACE; |
1047 IIC_SSTATEXT_END_PSL_TRACE; |
997 #endif |
1048 #endif |
998 return r; |
1049 return r; |
999 } |
1050 } |
1000 |
1051 |
1001 |
|
1002 |
|
1003 //#ifdef MASTER_MODE |
|
1004 #endif |
|
1005 |
|
1006 #if defined(MASTER_MODE) && defined(SLAVE_MODE) |
|
1007 #ifdef STANDALONE_CHANNEL |
1052 #ifdef STANDALONE_CHANNEL |
1008 EXPORT_C |
1053 EXPORT_C |
1009 #endif |
1054 #endif |
1010 DSimulatedIicBusChannelMasterSlaveI2c::DSimulatedIicBusChannelMasterSlaveI2c(TBusType /*aBusType*/, TChannelDuplex aChanDuplex, DSimulatedIicBusChannelMasterI2c* aMasterChan, DSimulatedIicBusChannelSlaveI2c* aSlaveChan) |
1055 DSimulatedIicBusChannelMasterSlaveI2c::DSimulatedIicBusChannelMasterSlaveI2c(TBusType /*aBusType*/, TChannelDuplex aChanDuplex, DSimulatedIicBusChannelMasterI2c* aMasterChan, DSimulatedIicBusChannelSlaveI2c* aSlaveChan) |
1011 : DIicBusChannelMasterSlave(EI2c, aChanDuplex, aMasterChan, aSlaveChan) |
1056 : DIicBusChannelMasterSlave(EI2c, aChanDuplex, aMasterChan, aSlaveChan) |