multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloaddecoder.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    DTMF RTP payload decoder for named telephone events
       
    15 *                and tones.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDES
       
    23 #include <mmf/server/mmfdatabuffer.h>
       
    24 #include "dtmfpayloaddecoder.h"
       
    25 #include "streamformatter.h"
       
    26 
       
    27 // CONSTANTS
       
    28 const TInt KBitIndex = 8;
       
    29 const TInt KReservedBits = 4;
       
    30 const TUint KMaxEventInteger = 9;
       
    31 
       
    32 #ifdef VOIP_TRACE_ENABLED
       
    33 #include <voip_trace.h>
       
    34 #endif
       
    35 
       
    36 // ======== MEMBER FUNCTIONS ========
       
    37 
       
    38 
       
    39 // ---------------------------------------------------------------------------
       
    40 // CDTMFPayloadDecoder::CDTMFPayloadDecoder
       
    41 // C++ default constructor can NOT contain any code, that
       
    42 // might leave.
       
    43 // ---------------------------------------------------------------------------
       
    44 //
       
    45 CDTMFPayloadDecoder::CDTMFPayloadDecoder()
       
    46     {
       
    47     }
       
    48 
       
    49 // ---------------------------------------------------------------------------
       
    50 // CDTMFPayloadDecoder::NewL
       
    51 // Two-phased constructor.
       
    52 // ---------------------------------------------------------------------------
       
    53 //
       
    54 CDTMFPayloadDecoder* CDTMFPayloadDecoder::NewL()
       
    55     {
       
    56     DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::NewL") );
       
    57     #ifdef VOIP_TRACE_ENABLED
       
    58         VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_NEWL );
       
    59     #endif
       
    60     
       
    61     CDTMFPayloadDecoder* self = new( ELeave ) CDTMFPayloadDecoder;
       
    62     return self;
       
    63     }
       
    64 
       
    65 // ---------------------------------------------------------------------------
       
    66 // CDTMFPayloadDecoder::~CDTMFPayloadDecoder
       
    67 // Destructor.
       
    68 // ---------------------------------------------------------------------------
       
    69 //
       
    70 CDTMFPayloadDecoder::~CDTMFPayloadDecoder()
       
    71     {
       
    72     DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::~CDTMFPayloadDecoder") );
       
    73     #ifdef VOIP_TRACE_ENABLED
       
    74         VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DESTRUCTOR );
       
    75     #endif
       
    76     
       
    77     iEventArray.Reset();
       
    78     }
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 // CDTMFPayloadDecoder::DecodeEventPayload
       
    82 // Decodes one DTMF digit or mutually exclusive events from Event Payload
       
    83 // Format packet.
       
    84 // ---------------------------------------------------------------------------
       
    85 //
       
    86 /*
       
    87     0                   1                   2                   3 
       
    88     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
    89    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
    90    |     event     |E|R| volume    |          duration             | 
       
    91    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
    92 */
       
    93 TInt CDTMFPayloadDecoder::DecodeEventPayload( CMMFBuffer* aSourceBuffer,
       
    94     RArray<TDTMFEventPayloadInfo>& aEventInfos )
       
    95     {
       
    96     DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::DecodeEventPayload") );
       
    97     #ifdef VOIP_TRACE_ENABLED
       
    98         VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECEVENTPAYLOAD,
       
    99         aSourceBuffer );
       
   100     #endif
       
   101     
       
   102     if ( EDTMFPayloadFormatRedEvents == iPayloadFormat )
       
   103         {
       
   104         return DecodeRedundantEventPayload( aSourceBuffer, aEventInfos );
       
   105         }
       
   106         
       
   107     if ( aSourceBuffer )
       
   108         {
       
   109         TDes8& dataDes = 
       
   110             static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
       
   111         const TUint8* seekPtr = dataDes.Ptr();
       
   112         TInt events = dataDes.Length( ) / KEventBlockLengthInBytes;
       
   113         
       
   114         TStreamDecoder streamDecoder;
       
   115         
       
   116         streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
       
   117         
       
   118         while ( events-- )
       
   119             {
       
   120             // Decode Event Field
       
   121             TInt eventCode = streamDecoder.Decode( KEventFieldBits );
       
   122             TChar charRepresentation;
       
   123             if ( KErrNone == ConvertToChar( eventCode, charRepresentation ) )
       
   124                 {
       
   125                 iDecodedEventInfo.SetEvent( charRepresentation );
       
   126                 
       
   127                 // Decode end bit for final packet
       
   128                 iDecodedEventInfo.SetEndBit( streamDecoder.Decode( 1 ) );
       
   129                 
       
   130                 // Decode reserved bit
       
   131                 streamDecoder.Decode( 1 );
       
   132                 
       
   133                 // Decode volume field.
       
   134                 // Volume field must be ignored if event 
       
   135                 // is not DTMF digit (RFC 2833)
       
   136                 if ( KEventCodeForD > eventCode )
       
   137                     {
       
   138                     iDecodedEventInfo.SetVolume( 
       
   139                                         streamDecoder.Decode(KVolFieldBits) );
       
   140                     }
       
   141                 else
       
   142                     {
       
   143                     streamDecoder.Decode( KVolFieldBits );
       
   144                     iDecodedEventInfo.SetVolume( 0 );
       
   145                     }
       
   146                 
       
   147                 // Decode duration field
       
   148                 iDecodedEventInfo.SetDuration( 
       
   149                                 streamDecoder.Decode(KDurationFieldBits) );
       
   150                 
       
   151                 // Time stamp from RTP header
       
   152                 iDecodedEventInfo.SetTimeStamp( iCurTimeStamp );
       
   153                 
       
   154                 aEventInfos.Append( iDecodedEventInfo );
       
   155                         
       
   156                 DP_DTMF_DECODE5(
       
   157                     _L( "Decoded event: %d, EndBit: %d, Volume: %d, Duration: %d" ),
       
   158                                  static_cast<TUint>( iDecodedEventInfo.Event() ), 
       
   159                                  iDecodedEventInfo.EndBit(), 
       
   160                                  iDecodedEventInfo.Volume(), 
       
   161                                  iDecodedEventInfo.Duration() );
       
   162                 }
       
   163             else
       
   164                 {
       
   165                 DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeEventPayload - Not supported event! ") );
       
   166                 }                
       
   167             }
       
   168         
       
   169         return KErrNone;    
       
   170         }
       
   171     else
       
   172         {
       
   173         return KErrArgument;
       
   174         }
       
   175     }    
       
   176 
       
   177 // ---------------------------------------------------------------------------
       
   178 // CDTMFPayloadDecoder::DecodeRedundantEventPayload
       
   179 // Decodes events from Event Payload Format where is used Multi-Event
       
   180 // Redundancy.
       
   181 // ---------------------------------------------------------------------------
       
   182 //
       
   183 /*
       
   184    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   185    |F|   block PT  |     timestamp offset      |   block length    | 
       
   186    |1|     97      |            11200          |         4         | 
       
   187    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   188    |F|   block PT  |     timestamp offset      |   block length    | 
       
   189    |1|     97      |   11200 - 6400 = 4800     |         4         | 
       
   190    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   191    |F|   Block PT  | 
       
   192    |0|     97      | 
       
   193    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   194    |     digit     |E R| volume    |          duration             | 
       
   195    |       9       |1 0|     7     |             1600              |  
       
   196    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   197    |     digit     |E R| volume    |          duration             | 
       
   198    |       1       |1 0|    10     |             2000              |  
       
   199    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   200    |     digit     |E R| volume    |          duration             | 
       
   201    |       1       |0 0|    20     |              400              |  
       
   202    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   203    */
       
   204 TInt CDTMFPayloadDecoder::DecodeRedundantEventPayload( 
       
   205     CMMFBuffer* aSourceBuffer,
       
   206     RArray<TDTMFEventPayloadInfo>& aEventInfos )
       
   207     {
       
   208     DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::DecodeRedundantEventPayload") );
       
   209     
       
   210     #ifdef VOIP_TRACE_ENABLED
       
   211         VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECREDEVPL, aSourceBuffer );
       
   212     #endif
       
   213     
       
   214     if ( aSourceBuffer )
       
   215         {
       
   216         TDes8& dataDes = 
       
   217             static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
       
   218         const TUint8* seekPtr = dataDes.Ptr();
       
   219         
       
   220         TStreamDecoder streamDecoder;
       
   221         
       
   222         streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
       
   223         
       
   224         aEventInfos.Reset();
       
   225         
       
   226         // Count events in a payload from the redundancy headers
       
   227         TInt eventCount( 0 );
       
   228         TBool FBitSet( ETrue );
       
   229         RArray< TTimeIntervalMicroSeconds32 > timeStamps;
       
   230         
       
   231         while ( FBitSet )
       
   232             {
       
   233             eventCount++;
       
   234             
       
   235             FBitSet = static_cast<TBool>( streamDecoder.Decode( 1 ) );
       
   236             streamDecoder.Decode( KBlockPTBits );
       
   237             
       
   238             if ( FBitSet )
       
   239                 {
       
   240                 TUint offset = streamDecoder.Decode( KTimeStampOffsetBits );
       
   241                 timeStamps.Append( TTimeIntervalMicroSeconds32( 
       
   242                                             iCurTimeStamp.Int() - offset ) );
       
   243                 }
       
   244             else
       
   245                 {
       
   246                 timeStamps.Append( TTimeIntervalMicroSeconds32( 
       
   247                                                     iCurTimeStamp.Int() ) );
       
   248                 }                
       
   249 
       
   250             // Jump to the beginning of next redundancy header
       
   251             streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 
       
   252                                 eventCount * KEventBlockLengthInBytes, 0 );
       
   253             }
       
   254 
       
   255         // Count index of first real event.
       
   256         // Last redundancy header consists of F-bit and PT only.
       
   257         streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 
       
   258                                   eventCount * KEventBlockLengthInBytes - 
       
   259                                   KEventBlockLengthInBytes, KBitIndex );
       
   260 
       
   261         // Decode all events from payload to the event info array.
       
   262         for ( TInt i = 0; i < eventCount; i++ )
       
   263             {
       
   264             // Decode Event Field
       
   265             TInt eventCode = streamDecoder.Decode( KEventFieldBits );
       
   266             TChar charRepresentation;
       
   267             
       
   268             if ( KErrNone == ConvertToChar( eventCode, charRepresentation ) )
       
   269                 {
       
   270                 iDecodedEventInfo.SetEvent( charRepresentation );
       
   271                 
       
   272                 // Decode end bit for final packet
       
   273                 iDecodedEventInfo.SetEndBit( streamDecoder.Decode( 1 ) );
       
   274                 
       
   275                 // Decode reserved bit
       
   276                 streamDecoder.Decode( 1 );
       
   277                 
       
   278                 // Decode volume field.
       
   279                 iDecodedEventInfo.SetVolume( streamDecoder.Decode( 
       
   280                                                             KVolFieldBits ) );
       
   281                 
       
   282                 // Decode duration field
       
   283                 iDecodedEventInfo.SetDuration( streamDecoder.Decode( 
       
   284                                                     KDurationFieldBits ) );
       
   285                 
       
   286                 // Set time stamp
       
   287                 iDecodedEventInfo.SetTimeStamp( timeStamps[i] );
       
   288                 
       
   289                 aEventInfos.Append( iDecodedEventInfo );
       
   290                 }
       
   291             else
       
   292                 {
       
   293                 DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeRedEventPayload" ) );
       
   294                 DP_DTMF_DECODE( _L( "- Not supported event! ") );
       
   295                 }                
       
   296             }
       
   297 
       
   298         timeStamps.Reset();
       
   299 
       
   300         // Delete already played events from the beginning of aEventInfos
       
   301         // array based on time stamp
       
   302         TInt latestRecordedEventInd( iEventArray.Count() - 1 );
       
   303         
       
   304         if ( 0 <= latestRecordedEventInd )
       
   305             {
       
   306             while ( aEventInfos.Count() && aEventInfos[0].TimeStamp() 
       
   307                 <= iEventArray[ latestRecordedEventInd ].TimeStamp() )
       
   308                 {
       
   309                 // Redundant event has earlier time stamp than latest played
       
   310                 // event we must delete this.
       
   311                 aEventInfos.Remove( 0 );
       
   312                 }
       
   313             }
       
   314 
       
   315         // Copy count of accepted events to the end of iEventArray and delete
       
   316         // same count from the beginning of array. Decoder must keep copies of
       
   317         // EventInfos, because PayloadFormatRead may make Reset() for a
       
   318         // aEventInfos Array.
       
   319         for ( TInt j = 0; j < aEventInfos.Count(); j++ )
       
   320             {
       
   321             iEventArray.Append( aEventInfos[ j ] );
       
   322             if ( KDTMFDefaultRedundancyCount < iEventArray.Count() )
       
   323                 {
       
   324                 iEventArray.Remove( 0 );
       
   325                 }
       
   326             }
       
   327 
       
   328         return KErrNone;
       
   329         }
       
   330     else
       
   331         {
       
   332         return KErrArgument;
       
   333         }
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------------------------
       
   337 // CDTMFPayloadDecoder::DecodeTonePayload
       
   338 // Decodes tones from Tone Payload Format packet.
       
   339 // Currently only DTMF tones are decoded (first tone).
       
   340 // Format of line event tones are unclear. Are multiple parts containing
       
   341 // line events encoded in one RTP packet or one part per RTP packet.
       
   342 // No proper support at DevSound / AudioServer to play out tone payload.
       
   343 // ---------------------------------------------------------------------------
       
   344 //
       
   345 /*
       
   346      0                   1                   2                   3 
       
   347      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   348     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   349     |    modulation   |T|  volume   |          duration             | 
       
   350     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   351     |R R R R|       frequency       |R R R R|       frequency       | 
       
   352     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   353     |R R R R|       frequency       |R R R R|       frequency       | 
       
   354     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   355         ...... 
       
   356     
       
   357     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   358     |R R R R|       frequency       |R R R R|      frequency        | 
       
   359     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
       
   360 */    
       
   361 TInt CDTMFPayloadDecoder::DecodeTonePayload( CMMFBuffer* aSourceBuffer,
       
   362     RArray<TDTMFTonePayloadInfo>& aToneInfos )
       
   363     {
       
   364     DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeTonePayload" ) );
       
   365     #ifdef VOIP_TRACE_ENABLED
       
   366         VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECTONEPL, aSourceBuffer );
       
   367     #endif
       
   368     
       
   369     if ( aSourceBuffer )
       
   370         {
       
   371         TDes8& dataDes = 
       
   372             static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
       
   373         const TUint8* seekPtr = dataDes.Ptr();
       
   374         
       
   375         TStreamDecoder streamDecoder;
       
   376         
       
   377         streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
       
   378         
       
   379         // Encode modulation field
       
   380         iDecodedToneInfo.SetModulation( streamDecoder.Decode( 
       
   381                                                         KModulationBits ) );
       
   382         
       
   383         // Encode T bit
       
   384         iDecodedToneInfo.SetTBit( streamDecoder.Decode( 1 ) );
       
   385         
       
   386         // Encode Volume Field
       
   387         iDecodedToneInfo.SetVolume( streamDecoder.Decode( KVolFieldBits ) );
       
   388         
       
   389         // Encode Duration Field
       
   390         iDecodedToneInfo.SetDuration( streamDecoder.Decode( 
       
   391                                                     KDurationFieldBits ) );
       
   392         
       
   393         // Encode four R(eserved) bits
       
   394         streamDecoder.Decode( KReservedBits );
       
   395         
       
   396         // Encode first Frequency Field
       
   397         iDecodedToneInfo.SetLowFrequency( streamDecoder.Decode( 
       
   398                                                         KFrequencyBits ) );
       
   399         
       
   400         // Encode four R(eserved) bits
       
   401         streamDecoder.Decode( KReservedBits );
       
   402         
       
   403         // Encode second Frequency Field
       
   404         iDecodedToneInfo.SetHighFrequency( streamDecoder.Decode( 
       
   405                                                         KFrequencyBits ) );
       
   406         
       
   407         aToneInfos.Append( iDecodedToneInfo );
       
   408         
       
   409         return KErrNone;
       
   410         }
       
   411     else
       
   412         {
       
   413         return KErrArgument;
       
   414         }
       
   415     }
       
   416 
       
   417 // ---------------------------------------------------------------------------
       
   418 // CDTMFPayloadDecoder::PayloadFormat
       
   419 // Returns payload format in use.
       
   420 // ---------------------------------------------------------------------------
       
   421 //
       
   422 TDTMFPayloadFormat CDTMFPayloadDecoder::PayloadFormat( ) const
       
   423     {
       
   424     DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::PayloadFormat - Format: %d" ),
       
   425         iPayloadFormat );
       
   426     
       
   427     return iPayloadFormat;
       
   428     }
       
   429 
       
   430 // ---------------------------------------------------------------------------
       
   431 // CDTMFPayloadDecoder::SetPayloadFormat
       
   432 // Sets payload format in use.
       
   433 // ---------------------------------------------------------------------------
       
   434 //    
       
   435 TInt CDTMFPayloadDecoder::SetPayloadFormat( 
       
   436     TDTMFPayloadFormat aPayloadFormat )
       
   437     {
       
   438     DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::SetPayloadFormat - Format: %d" ),
       
   439         aPayloadFormat );
       
   440     #ifdef VOIP_TRACE_ENABLED
       
   441         VoipTrace( "%x %x %d", MCC_TRACE, MCC_DTMF_PLF_DEC_SETPLF, aPayloadFormat );
       
   442     #endif
       
   443     
       
   444     if ( EDTMFPayloadFormatEvent != aPayloadFormat
       
   445          && EDTMFPayloadFormatTone != aPayloadFormat
       
   446          && EDTMFPayloadFormatRedEvents != aPayloadFormat )
       
   447         {
       
   448         return KErrNotSupported;
       
   449         }
       
   450     else
       
   451         {
       
   452         iPayloadFormat = aPayloadFormat;
       
   453         }
       
   454         
       
   455     return KErrNone;
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // CDTMFPayloadDecoder::SetCurTimeStamp
       
   460 // Sets the time stamp of a RTP packet containing payload which is decoded 
       
   461 // next.
       
   462 // ---------------------------------------------------------------------------
       
   463 //      
       
   464 void CDTMFPayloadDecoder::SetCurTimeStamp( 
       
   465     const TTimeIntervalMicroSeconds32& aTimeStamp )
       
   466     {
       
   467     DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::SetCurTimeStamp - TimeStamp: %d" ),
       
   468         aTimeStamp.Int() );
       
   469         
       
   470     #ifdef VOIP_TRACE_ENABLED
       
   471         VoipTrace( "%x %x %d", MCC_TRACE, MCC_DTMF_PLF_DEC_SETCURTS, aTimeStamp.Int() );
       
   472     #endif
       
   473     
       
   474     iCurTimeStamp = aTimeStamp;
       
   475     }
       
   476 
       
   477 // ---------------------------------------------------------------------------
       
   478 // CDTMFPayloadDecoder::ConvertToChar
       
   479 // Converts integer presentation used in a payload format to the character.
       
   480 // ---------------------------------------------------------------------------
       
   481 //
       
   482 TInt CDTMFPayloadDecoder::ConvertToChar( TUint aEvent, TChar& aChar ) const
       
   483     {
       
   484     TInt conversionResult( KErrNone );
       
   485 
       
   486     if ( aEvent <= KMaxEventInteger )
       
   487         {
       
   488         aChar = TChar( aEvent + '0' );
       
   489         }
       
   490     else
       
   491         {
       
   492         switch ( aEvent )
       
   493             {
       
   494             case KEventCodeForAsterisk:
       
   495                 aChar = '*';
       
   496                 break;
       
   497             case KEventCodeForHashMark:
       
   498                 aChar = '#';
       
   499                 break;
       
   500             case KEventCodeForA:
       
   501                 aChar = 'a';
       
   502                 break;
       
   503             case KEventCodeForB:
       
   504                 aChar = 'b';
       
   505                 break;
       
   506             case KEventCodeForC:
       
   507                 aChar = 'c';
       
   508                 break;
       
   509             case KEventCodeForD:
       
   510                 aChar = 'd';
       
   511                 break;
       
   512             default:
       
   513                 conversionResult = KErrNotSupported;
       
   514                 break;
       
   515             }
       
   516         }    
       
   517 
       
   518     return conversionResult;
       
   519     }
       
   520 
       
   521 //  End of File