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