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"); |
123 if(size>maxLen) |
124 if(size>maxLen) |
124 size=maxLen; |
125 size=maxLen; |
125 aDes.Copy((TUint8*)&caps,size); |
126 aDes.Copy((TUint8*)&caps,size); |
126 } |
127 } |
127 |
128 |
|
129 #ifndef STANDALONE_CHANNEL |
128 // supported channels for this implementation |
130 // supported channels for this implementation |
129 static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS]; |
131 static DIicBusChannel* ChannelPtrArray[NUM_CHANNELS]; |
130 |
132 #endif |
131 |
133 |
132 //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY) |
134 //DECLARE_EXTENSION_WITH_PRIORITY(BUS_IMPLMENTATION_PRIORITY) |
133 DECLARE_STANDARD_PDD() // I2c test driver to be explicitly loaded as an LDD, not kernel extension |
135 DECLARE_STANDARD_PDD() // I2c test driver to be explicitly loaded as an LDD, not kernel extension |
134 { |
136 { |
135 #ifndef STANDALONE_CHANNEL |
137 #ifndef STANDALONE_CHANNEL |
437 #ifdef SLAVE_MODE |
439 #ifdef SLAVE_MODE |
438 |
440 |
439 void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr) |
441 void DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback(TAny* aPtr) |
440 { |
442 { |
441 // To support simulating an asynchronous capture operation |
443 // To support simulating an asynchronous capture operation |
442 // NOTE: this will be invoked in the context of DfcThread1 |
|
443 I2C_PRINT(("SlaveAsyncSimCallback\n")); |
444 I2C_PRINT(("SlaveAsyncSimCallback\n")); |
444 DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr; |
445 DSimulatedIicBusChannelSlaveI2c* channel = (DSimulatedIicBusChannelSlaveI2c*)aPtr; |
445 TInt r=KErrNone;// Just simulate successful capture |
446 |
446 #ifdef IIC_INSTRUMENTATION_MACRO |
447 // This will be invoked in the context of DfcThread1, so require |
447 IIC_SCAPTCHANASYNC_END_PSL_TRACE; |
448 // synchronised access to iAsyncEvent and iRxTxTrigger |
448 #endif |
449 // Use local variables to enable early release of the spin lock |
449 channel->ChanCaptureCb(r); |
450 // |
|
451 // If DfcThread1 runs on a separate core to the simulated I2C bus, the other core |
|
452 // will have updated values, and since this core may cached copies, memory access |
|
453 // should be observed. The spin lock mechanism is expected to incorpoate this. |
|
454 TInt intState=__SPIN_LOCK_IRQSAVE(channel->iEventSpinLock); |
|
455 |
|
456 TAsyncEvent asyncEvent = channel->iAsyncEvent; |
|
457 TInt rxTxTrigger = channel->iRxTxTrigger; |
|
458 channel->iAsyncEvent = ENoEvent; |
|
459 channel->iRxTxTrigger = 0; |
|
460 __SPIN_UNLOCK_IRQRESTORE(channel->iEventSpinLock,intState); |
|
461 |
|
462 switch(asyncEvent) |
|
463 { |
|
464 case (EAsyncChanCapture): |
|
465 { |
|
466 TInt r=KErrNone;// Just simulate successful capture |
|
467 #ifdef IIC_INSTRUMENTATION_MACRO |
|
468 IIC_SCAPTCHANASYNC_END_PSL_TRACE; |
|
469 #endif |
|
470 channel->ChanCaptureCb(r); |
|
471 break; |
|
472 } |
|
473 case (ERxWords): |
|
474 case (ETxWords): |
|
475 case (ERxTxWords): |
|
476 { |
|
477 channel->ChanNotifyClient(rxTxTrigger); |
|
478 break; |
|
479 } |
|
480 default: |
|
481 { |
|
482 } |
|
483 } |
450 } |
484 } |
451 |
485 |
452 #ifdef STANDALONE_CHANNEL |
486 #ifdef STANDALONE_CHANNEL |
453 EXPORT_C |
487 EXPORT_C |
454 #endif |
488 #endif |
455 DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex) |
489 DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c(const DIicBusChannel::TBusType aBusType, const DIicBusChannel::TChannelDuplex aChanDuplex) |
456 : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class |
490 : DIicBusChannelSlave(aBusType,aChanDuplex,0), // 0 to be ignored by base class |
457 iBlockedTrigger(0),iBlockNotification(EFalse), |
491 iBlockedTrigger(0),iBlockNotification(EFalse),iAsyncEvent(ENoEvent),iRxTxTrigger(0), |
458 iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this) |
492 iSlaveTimer(DSimulatedIicBusChannelSlaveI2c::SlaveAsyncSimCallback,this), |
|
493 iEventSpinLock(TSpinLock::EOrderGenericIrqHigh2) // Semi-arbitrary, high priority value (NTimer used) |
459 { |
494 { |
460 I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex)); |
495 I2C_PRINT(("DSimulatedIicBusChannelSlaveI2c::DSimulatedIicBusChannelSlaveI2c, aBusType=%d,aChanDuplex=%d\n",aBusType,aChanDuplex)); |
461 #ifndef STANDALONE_CHANNEL |
496 #ifndef STANDALONE_CHANNEL |
462 iChannelNumber = AssignChanNum(); |
497 iChannelNumber = AssignChanNum(); |
463 #endif |
498 #endif |
486 { |
521 { |
487 #ifdef IIC_INSTRUMENTATION_MACRO |
522 #ifdef IIC_INSTRUMENTATION_MACRO |
488 IIC_SCAPTCHANASYNC_START_PSL_TRACE; |
523 IIC_SCAPTCHANASYNC_START_PSL_TRACE; |
489 #endif |
524 #endif |
490 // To simulate an asynchronous capture operation, just set a timer to expire |
525 // 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 |
526 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
527 iAsyncEvent = EAsyncChanCapture; |
|
528 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
529 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
492 } |
530 } |
493 else |
531 else |
494 { |
532 { |
495 #ifdef IIC_INSTRUMENTATION_MACRO |
533 #ifdef IIC_INSTRUMENTATION_MACRO |
496 IIC_SCAPTCHANSYNC_START_PSL_TRACE; |
534 IIC_SCAPTCHANSYNC_START_PSL_TRACE; |
707 } |
744 } |
708 } |
745 } |
709 if(iBlockNotification == EFalse) |
746 if(iBlockNotification == EFalse) |
710 { |
747 { |
711 // |
748 // |
712 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
749 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
713 NotifyClient(trigger); |
750 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
751 // Tx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
752 iRxTxTrigger |= trigger; |
|
753 iAsyncEvent = ERxWords; |
|
754 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
755 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
714 } |
756 } |
715 else |
757 else |
716 { |
758 { |
717 // Save the trigger value to notify when prompted. |
759 // Save the trigger value to notify when prompted. |
718 iBlockedTrigger=trigger; |
760 iBlockedTrigger=trigger; |
782 *dstPtr++=*srcPtr++; |
824 *dstPtr++=*srcPtr++; |
783 } |
825 } |
784 if(iBlockNotification == EFalse) |
826 if(iBlockNotification == EFalse) |
785 { |
827 { |
786 // |
828 // |
787 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
829 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
788 NotifyClient(trigger); |
830 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
831 // Rx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
832 iRxTxTrigger |= trigger; |
|
833 iAsyncEvent = ETxWords; |
|
834 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
835 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
|
836 // No effect if OneShot already invoked |
789 } |
837 } |
790 else |
838 else |
791 { |
839 { |
792 // Save the trigger value to notify when prompted. |
840 // Save the trigger value to notify when prompted. |
793 iBlockedTrigger=trigger; |
841 iBlockedTrigger=trigger; |
866 } |
914 } |
867 |
915 |
868 if(iBlockNotification == EFalse) |
916 if(iBlockNotification == EFalse) |
869 { |
917 { |
870 // |
918 // |
871 // Invoke DIicBusChannelSlave::NotifyClient - this will invoke ProcessData and invoke the client callback |
919 // Use a timer for asynchronous call to NotifyClient - this will invoke ProcessData and invoke the client callback |
872 NotifyClient(trigger); |
920 TInt intState=__SPIN_LOCK_IRQSAVE(iEventSpinLock); |
|
921 // Rx or Tx may already have been requested, to add to the existing flags set in iRxTxTrigger |
|
922 iRxTxTrigger |= trigger; |
|
923 iAsyncEvent = ERxTxWords; |
|
924 __SPIN_UNLOCK_IRQRESTORE(iEventSpinLock,intState); |
|
925 iSlaveTimer.OneShot(KI2cSlaveAsyncDelaySim, ETrue); // Arbitrary timeout - expiry executes callback in context of DfcThread1 |
873 } |
926 } |
874 else |
927 else |
875 { |
928 { |
876 // Save the trigger value to notify when prompted. |
929 // Save the trigger value to notify when prompted. |
877 iBlockedTrigger=trigger; |
930 iBlockedTrigger=trigger; |