connectivitylayer/isce/isirouter_dll/src/isiuserchannel.cpp
changeset 0 63b37f68c1ce
child 9 8486d82aef45
equal deleted inserted replaced
-1:000000000000 0:63b37f68c1ce
       
     1 /*
       
     2 * Copyright (c) 2009 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 the License "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: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <kern_priv.h>              // For DMutex
       
    21 #include "isiuserchannel.h"         // For DISIUserChanneel
       
    22 #include "isiroutertrace.h"         // For C_TRACE, ASSERT_RESET.. and fault codes
       
    23 #include "misichannelrouterif.h"    // For MISIChannelRouterIf
       
    24 #include "memapi.h"                 // For MemApi
       
    25 #include "isimsgqueue.h"            // For DISIMsgQueue
       
    26 
       
    27 const TInt KFirstParam( 0 );
       
    28 const TInt KSecondParam( 1 );
       
    29 const TInt KThirdParam( 2 );
       
    30 const TInt KNoParams( 0 );
       
    31 const TInt KOneParam( 1 );
       
    32 const TInt KTwoParams( 2 );
       
    33 const TInt KThreeParams( 3 );
       
    34 const TInt KFirstRequest( 0 );
       
    35 const TInt KDestStartOffset( 0 );
       
    36 
       
    37 enum TISIUserChannelFaults
       
    38     {
       
    39     EISIUserChannelMemAllocFail = 0x01,
       
    40     EISIUserChannelMemAllocFail1,
       
    41     EISIUserChannelMemAllocFail2,
       
    42     EISIUserChannelMemAllocFail3,
       
    43     EISIUserChannelWrongRequest,
       
    44     EISIUserChannelWrongRequest1,
       
    45     EISIUserChannelWrongRequest2,
       
    46     EISIUserChannelWrongRequest3,
       
    47     EISIUserChannelWrongRequest4,
       
    48     EISIUserChannelWrongRequest5,
       
    49     EISIUserChannelWrongRequest6,
       
    50     EISIUserChannelReqOverTheLimits,
       
    51     EISIUserChannelDesWriteFailed,
       
    52     EISIUserChannelSameRequest,
       
    53     EISIUserChannelNullParam,
       
    54     EISIUserChannelNullParam2,
       
    55     EISIUserChannelDesReadFailed,
       
    56     EISIUserChannelfNotThreadContext,
       
    57     EISIUserChannelfNotThreadContext2,
       
    58     EISIUserChannelfNotThreadContext3,
       
    59     EISIUserChannelfNotThreadContext4,
       
    60     EISIUserChannelfNotThreadContext5,
       
    61     };
       
    62 
       
    63 const TInt KISILddEmptyRxQueuePriori( 1 );
       
    64 const TInt KISILddCompleteRequestPriori( 1 );
       
    65 
       
    66 
       
    67 // user<> kernel interaction() done in LDD DFC thread
       
    68 // 
       
    69 // kernel<>kernel interaction() done in Extension DFC thread
       
    70 //
       
    71 // DEMAND_PAGING
       
    72 // Receive (write k>u) is done only in LDD thread context to allow Extension thread to continue when dp swaps.
       
    73 // Send ((write u>k) is not done at the moment in LDD thread context only. Check is it possible to happend (not to be in usable memory after send (unlikely?)).
       
    74 
       
    75 DISIUserChannel::DISIUserChannel(
       
    76         // None
       
    77         ) : iThread( &Kern::CurrentThread()),
       
    78             iObjId( KNotInitializedId ),
       
    79             iUID( KNotInitializedUID )
       
    80     {
       
    81     C_TRACE( ( _T( "DISIUserChannel::DISIUserChannel>" ) ) );
       
    82     iRouterIf = MISIChannelRouterIf::GetIf();
       
    83     ASSERT_RESET_ALWAYS( iRouterIf, ( EISIUserChannelMemAllocFail | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
    84     iCompletionThread = iRouterIf->GetDfcThread( MISIChannelRouterIf::EISIUserRequestCompletionThread );
       
    85     iEmptyRxQueueDfc = new TDfc( EmptyRxQueueDfc, this, iCompletionThread, KISILddEmptyRxQueuePriori );
       
    86     ASSERT_RESET_ALWAYS( iEmptyRxQueueDfc, ( EISIUserChannelMemAllocFail2 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
    87     iCompleteChannelRequestDfc = new TDfc( CompleteChannelRequestDfc, this, iCompletionThread, KISILddCompleteRequestPriori );
       
    88     ASSERT_RESET_ALWAYS( iCompleteChannelRequestDfc, ( EISIUserChannelMemAllocFail3 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
    89     iRequests = new DISIUserAsyncRequests( EISILastAsyncRequest );   
       
    90     C_TRACE( ( _T( "DISIUserChannel::DISIUserChannel<" ) ) );
       
    91     }
       
    92 
       
    93 DISIUserChannel::~DISIUserChannel(
       
    94         // None
       
    95         )
       
    96     {
       
    97     C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x>" ), this ) );
       
    98      // owned starts
       
    99     if( iEmptyRxQueueDfc )
       
   100         {
       
   101         C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x 0x%x iEmptyRxQueueDfc 0x%x" ), this, iObjId, iEmptyRxQueueDfc ) );
       
   102         iEmptyRxQueueDfc->Cancel();
       
   103         delete iEmptyRxQueueDfc;
       
   104         iEmptyRxQueueDfc = NULL;
       
   105         }
       
   106     if( iCompleteChannelRequestDfc )
       
   107         {
       
   108         C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x 0x%x iCompleteChannelRequestDfc 0x%x" ), this, iObjId, iCompleteChannelRequestDfc ) );
       
   109         iCompleteChannelRequestDfc->Cancel();
       
   110         delete iCompleteChannelRequestDfc;
       
   111         iCompleteChannelRequestDfc = NULL;
       
   112         }
       
   113     if( iRx )
       
   114         {
       
   115         C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x 0x%x iRx 0x%x" ), this, iObjId, iRx ) );
       
   116         delete iRx;
       
   117         iRx = NULL;
       
   118         }
       
   119     if( iReceiveBufPtr )
       
   120         {
       
   121         C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x 0x%x iReceiveBufPtr 0x%x" ), this, iObjId, iReceiveBufPtr ) );
       
   122         iReceiveBufPtr = NULL;
       
   123         }
       
   124     if( iRequests )
       
   125         {
       
   126         delete iRequests;
       
   127         iRequests = NULL;
       
   128         }
       
   129     // owned ends
       
   130     iRouterIf = NULL;
       
   131     Kern::SafeClose( reinterpret_cast<DObject*&>(iThread), NULL );    
       
   132     C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x<" ), this ) );
       
   133     }
       
   134 
       
   135 /*
       
   136 * Executed in user thread context thread inside CS, cannot be pre-empted.
       
   137 * Channel can not be used before creation, so no need to synch if congesting only btw the creating user thread and one thread.
       
   138 */    
       
   139 TInt DISIUserChannel::DoCreate(
       
   140         TInt, //aUnit,              // Not used at the moment
       
   141         const TDesC8*, //anInfo,    // Not used at the moment.
       
   142         const TVersion& // aVer     // Not used at the moment.
       
   143         )
       
   144     {
       
   145     C_TRACE( ( _T( "DISIUserChannel::DoCreate 0x%x 0x%x>" ), this, iObjId ) );
       
   146     if( !Kern::CurrentThreadHasCapability( ECapabilityCommDD, __PLATSEC_DIAGNOSTIC_STRING( "Check by: ISI Router" ) ) ) return KErrPermissionDenied;
       
   147     iRx = new DISIMsgQueue( KISILddRxQueueSize );
       
   148     ASSERT_RESET_ALWAYS( iRx, ( EISIUserChannelMemAllocFail1 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   149     // Other DFC functions handling user<>kernel copying done in ldd DFC. Ldd DFC function priority is 1.
       
   150     iMainThread = iRouterIf->GetDfcThread( MISIChannelRouterIf::EISIUserMainThread );
       
   151     SetDfcQ( iMainThread );
       
   152     iMsgQ.Receive();
       
   153     DObject* thread = reinterpret_cast<DObject*>( iThread );
       
   154     // Open is needed to increase ref count to calling thread that is decreased in Kern::SafeClose
       
   155     // Possible returns KErrNone ? KErrGeneral
       
   156     TInt threadOpen( thread->Open() );
       
   157     TRACE_ASSERT_INFO( threadOpen == KErrNone, iObjId );
       
   158     C_TRACE( ( _T( "DISIUserChannel::DoCreate 0x%x 0x%x<" ), this, iObjId ) );
       
   159     return threadOpen;
       
   160     }
       
   161 
       
   162 void DISIUserChannel::HandleMsg(
       
   163         TMessageBase* aMsg
       
   164         )
       
   165     {
       
   166     C_TRACE( ( _T( "DISIUserChannel::HandleMsg 0x%x 0x%x 0x%x>" ), this, aMsg, iObjId ) );
       
   167     TThreadMessage& m= *( static_cast< TThreadMessage* >( aMsg ) );
       
   168     TInt id( m.iValue );
       
   169     if( static_cast<TInt>( ECloseMsg ) == id )
       
   170         {
       
   171         C_TRACE( ( _T( "DISIUserChannel::HandleMsg ECloseMsg 0x%x 0x%x" ), this, aMsg ) );
       
   172         m.Complete( HandleSyncRequest( EISIDisconnect, NULL ), EFalse );
       
   173         }
       
   174     else if( KMaxTInt == id )
       
   175         {
       
   176         C_TRACE( ( _T( "DISIUserChannel::HandleMsg cancel 0x%x 0x%x" ), this, aMsg ) );
       
   177         DoCancel( id, m.Int0() );
       
   178         m.Complete( KErrNone, ETrue );
       
   179         }
       
   180     else
       
   181         {
       
   182         ASSERT_RESET_ALWAYS( ( KErrNotFound < id ), ( EISIUserChannelWrongRequest | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   183         C_TRACE( ( _T( "DISIUserChannel::HandleMsg request 0x%x %d 0x%x" ), this, id, aMsg ) );
       
   184         TInt completeValue( KErrNone );
       
   185         TInt ulen( KErrNotFound );
       
   186         switch ( id )
       
   187             {
       
   188             case EISIDisconnect:
       
   189                 {
       
   190                 ulen = KNoParams;
       
   191                 break;
       
   192                 }
       
   193             case EISISend:
       
   194                 {
       
   195                 ulen = KOneParam;
       
   196                 break;
       
   197                 }
       
   198             case EISIConnect:
       
   199                 {
       
   200                 ulen = KTwoParams;
       
   201                 break;
       
   202                 }
       
   203             case EISIAsyncReceive:
       
   204                 {
       
   205                 ulen = KThreeParams;
       
   206                 break;
       
   207                 }
       
   208             default:
       
   209                 {
       
   210                 ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelWrongRequest1 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   211                 break;
       
   212                 }
       
   213             }
       
   214         TUint32* table[ KThreeParams ];
       
   215         completeValue = Kern::ThreadRawRead( iThread, m.Ptr0(), table, ulen * sizeof( TAny* ) );
       
   216         
       
   217         if( completeValue == KErrNone )
       
   218             {
       
   219             switch( id )
       
   220                 {
       
   221                 // All asynchronous requests.
       
   222                 case EISIAsyncReceive:
       
   223                     {
       
   224                     // No need to check return value in async functions, completed to user
       
   225                     HandleAsyncRequest( id, table );
       
   226                     break;
       
   227                     }
       
   228                 case EISIDisconnect:
       
   229                 case EISIConnect:
       
   230                 case EISISend:
       
   231                     {
       
   232                     completeValue = HandleSyncRequest( id, table );
       
   233                     break;
       
   234                     }
       
   235                 default:
       
   236                     {
       
   237                     ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelWrongRequest2 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   238                     break;
       
   239                     }
       
   240                 }
       
   241             }
       
   242         m.Complete( completeValue, ETrue );
       
   243         }
       
   244     C_TRACE( ( _T( "DISIUserChannel::HandleMsg 0x%x 0x%x 0x%x<" ), this, aMsg, iObjId ) );
       
   245     }
       
   246 
       
   247 TInt DISIUserChannel::Request(
       
   248         TInt aReqNo,
       
   249         TAny* a1,
       
   250         TAny* //a2
       
   251         )
       
   252     {
       
   253     C_TRACE( ( _T( "DISIUserChannel::Request 0x%x %d 0x%x 0x%x>" ), this, aReqNo, a1, iObjId ) );
       
   254     // Programmer errors.
       
   255     ASSERT_RESET_ALWAYS( aReqNo >= ( TInt ) EMinRequestId, ( EISIUserChannelWrongRequest3 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   256     ASSERT_RESET_ALWAYS( ( aReqNo <= EISILastAsyncRequest || aReqNo == KMaxTInt ), ( EISIUserChannelWrongRequest4 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   257     // Wrong API usage e.g. called function when interface is not open so panic the client thread.
       
   258     TInt result( KErrNotFound );
       
   259     // All request go in kernel context and with ::DoControl call.
       
   260     TThreadMessage& m=Kern::Message();
       
   261     m.iValue = aReqNo;
       
   262     m.iArg[ KFirstParam ] = a1;
       
   263     m.iArg[ KSecondParam ] = NULL;
       
   264     result = m.SendReceive( &iMsgQ );
       
   265     C_TRACE( ( _T( "DISIUserChannel::Request 0x%x %d 0x%x<" ), this, aReqNo, a1, iObjId ) );
       
   266     return result;
       
   267     }
       
   268 
       
   269 TInt DISIUserChannel::HandleSyncRequest(
       
   270         TInt aRequest,
       
   271         TAny* a1
       
   272         )
       
   273     {
       
   274     C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest 0x%x %d 0x%x 0x%x>" ), this, aRequest, a1, iObjId ) );
       
   275     ASSERT_THREAD_CONTEXT_ALWAYS( ( EISIUserChannelfNotThreadContext5 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   276     TInt error( KErrNotSupported );
       
   277     switch( aRequest )
       
   278         {
       
   279         case EISIDisconnect:
       
   280             {
       
   281             C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest 0x%x EISIDisconnect" ), this ) );
       
   282             Disconnect();
       
   283             error = KErrNone;
       
   284             break;
       
   285             }
       
   286         case EISISend:
       
   287             {
       
   288             C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest 0x%x EISISend" ), this ) );
       
   289             TUint32* tablePtr = reinterpret_cast<TUint32*>( a1 );
       
   290             TAny* firstParam = reinterpret_cast<TAny*>( tablePtr[ KFirstParam ] );
       
   291             TRACE_ASSERT_INFO( firstParam, ( iObjId << KObjIdShift | ( EISIUserChannelNullParam2 | EDISIUserChannelTraceId << KClassIdentifierShift ) ) );
       
   292             TInt msgLength( Kern::ThreadGetDesLength( iThread, firstParam ) );
       
   293             C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest 0x%x EISISend 0x%x %d" ), this, firstParam, msgLength ) );
       
   294             if( msgLength > 0 && msgLength < KMaxISIMsgSize )
       
   295                 {
       
   296                 TDes8& sendBlock = MemApi::AllocBlock( msgLength );
       
   297                 ASSERT_RESET_ALWAYS( KErrNone == Kern::ThreadDesRead( iThread, firstParam, sendBlock, 0, KChunkShiftBy0 ), ( EISIUserChannelDesReadFailed | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   298                 TRACE_ASSERT_INFO( sendBlock.Length() == msgLength, iObjId << KObjIdShift );
       
   299                 C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest EISISend 0x%x 0x%x" ), this, &sendBlock ) );
       
   300                 error = iRouterIf->Send( sendBlock, iObjId );
       
   301                 }
       
   302             else
       
   303                 {
       
   304                 error = ( msgLength > KMaxISIMsgSize ) ? KErrNoMemory : KErrBadDescriptor;
       
   305                 TRACE_ASSERT_INFO( 0, iObjId << KObjIdShift | (TUint16)msgLength );
       
   306                 }
       
   307             break;
       
   308             }
       
   309         case EISIConnect:
       
   310             {
       
   311             TUint32* tablePtr = reinterpret_cast<TUint32*>( a1 );
       
   312             iUID = tablePtr[ KFirstParam ];
       
   313             TUint8* objIdPtr = reinterpret_cast<TUint8*>( tablePtr[ KSecondParam ] );
       
   314             C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest EISIConnect 0x%x 0x%x 0x%x" ), this, iUID, objIdPtr ) );
       
   315             iRouterIf->Connect( iUID, iObjId, this );
       
   316             C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest received iObjId is 0x%x" ), iObjId ) );
       
   317             ASSERT_RESET_ALWAYS( KErrNone == Kern::ThreadRawWrite( iThread, objIdPtr, &iObjId, sizeof(TUint8), iThread ), 
       
   318                                    EISIUserChannelDesWriteFailed | iObjId << KObjIdShift | EDISIUserChannelTraceId << KClassIdentifierShift );
       
   319             error = KErrNone;
       
   320             break;            
       
   321             }
       
   322         default:
       
   323             {
       
   324             ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelWrongRequest5 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   325             break;
       
   326             }
       
   327         }
       
   328     C_TRACE( ( _T( "DISIUserChannel::HandleSyncRequest 0x%x %d 0x%x 0x%x<" ), this, aRequest, a1, iObjId ) );
       
   329     return error;
       
   330     }
       
   331 
       
   332 void DISIUserChannel::HandleAsyncRequest(
       
   333         TInt aRequest,
       
   334         TAny* a1
       
   335         )
       
   336     {
       
   337     C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest 0x%x %d 0x%x 0x%x>" ), this, aRequest, a1, iObjId ) );
       
   338     
       
   339     ASSERT_THREAD_CONTEXT_ALWAYS( ( EISIUserChannelfNotThreadContext4 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   340     TUint32* tablePtr = reinterpret_cast<TUint32*>( a1 );
       
   341     TRACE_ASSERT_INFO( tablePtr[ KFirstParam ], (TUint16)aRequest );
       
   342     TRequestStatus* requestStatus = reinterpret_cast<TRequestStatus*>( tablePtr[ KFirstParam ] );
       
   343     if( iRequests->IsPending( aRequest ) )
       
   344         {
       
   345         C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest existing 0x%x request 0x%x" ), this, aRequest ) );
       
   346         // Should not give same request object twice before completing the first one.
       
   347         ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelSameRequest | iObjId << KObjIdShift | static_cast<TUint8>( aRequest ) << KExtraInfoShift ) );
       
   348         }
       
   349     else
       
   350         {
       
   351         C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest 0x%x handling %d" ), this, aRequest ) );
       
   352         iRequests->SetPending( aRequest, requestStatus );
       
   353         switch( aRequest )
       
   354             {
       
   355             case EISIAsyncReceive:
       
   356                 {
       
   357                 iReceiveBufPtr = reinterpret_cast<TAny*>( tablePtr[ KSecondParam ] );
       
   358                 iNeededBufLen = reinterpret_cast<TUint16*>( tablePtr[ KThirdParam ] );
       
   359                 C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest 0x%x EISIAsyncReceive 0x%x" ), this, iReceiveBufPtr ) );
       
   360                 iEmptyRxQueueDfc->Enque();
       
   361                 break;
       
   362                 }
       
   363             default:
       
   364                 {
       
   365                 ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelWrongRequest2 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   366                 break;
       
   367                 }
       
   368             }
       
   369         }
       
   370     C_TRACE( ( _T( "DISIUserChannel::HandleAsyncRequest 0x%x %d 0x%x 0x%x<" ), this, aRequest, a1, iObjId ) );
       
   371     }
       
   372     	
       
   373 
       
   374 void DISIUserChannel::DoCancel(
       
   375         TInt aRequest,
       
   376         TInt aMask )
       
   377     {
       
   378     C_TRACE( ( _T( "DISIUserChannel::DoCancel 0x%x %d 0x%x 0x%x>" ), this, aRequest, aMask, iObjId ) );
       
   379     switch( aMask&aRequest )
       
   380         {
       
   381         case EISIAsyncReceive:
       
   382             {
       
   383             C_TRACE( ( _T( "DISIUserChannel::DoCancel 0x%x EISIAsyncReceive 0x%x " ), this, iReceiveBufPtr ) );
       
   384             iReceiveBufPtr = NULL;
       
   385             break;
       
   386             }
       
   387         default:
       
   388             {
       
   389             ASSERT_RESET_ALWAYS( 0, ( EISIUserChannelWrongRequest6 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   390             break;
       
   391             }
       
   392         }
       
   393     EnqueChannelRequestCompleteDfc( aMask&aRequest, KErrCancel );
       
   394     C_TRACE( ( _T( "DISIUserChannel::DoCancel 0x%x %d 0x%x 0x%x<" ), this, aRequest, aMask, iObjId ) );
       
   395     }
       
   396     	
       
   397 
       
   398 void DISIUserChannel::Disconnect(
       
   399         // None
       
   400         )
       
   401     {
       
   402     C_TRACE( ( _T( "DISIUserChannel::Disconnect 0x%x 0x%x>" ), this, iObjId ) );
       
   403     ResetQueues();
       
   404     for( TInt i( 0 ); i < iRequests->iRequestCompletedList.Count(); ++i )
       
   405         {
       
   406         C_TRACE( ( _T( "DISIUserChannel::CancelRequests req to cancel %d" ), i ) );
       
   407         DoCancel( KMaxTInt, i );
       
   408         }
       
   409     iRouterIf->Disconnect( iObjId );
       
   410     iRouterIf->FreeDfcThread( iMainThread );
       
   411     iRouterIf->FreeDfcThread( iCompletionThread );    
       
   412     C_TRACE( ( _T( "DISIUserChannel::Disconnect 0x%x 0x%x<" ), this, iObjId ) );
       
   413     }
       
   414 
       
   415 void DISIUserChannel::ResetQueues(
       
   416         // None
       
   417         )
       
   418     {
       
   419     C_TRACE( ( _T( "DISIUserChannel::ResetQueues 0x%x 0x%x>" ), this, iObjId ) );
       
   420     if( iRx )
       
   421         {
       
   422         C_TRACE( ( _T( "DISIUserChannel::ResetQueues 0x%x iRx 0x%x" ), this, iRx ) );
       
   423         while( iRx->Count() )
       
   424             {
       
   425             MemApi::DeallocBlock( iRx->Get() );
       
   426             }
       
   427         }
       
   428     C_TRACE( ( _T( "DISIUserChannel::ResetQueues 0x%x 0x%x<" ), this, iObjId ) );
       
   429     }
       
   430 
       
   431 // This is called in 1...N thread contextes
       
   432 void DISIUserChannel::ReceiveMsg(
       
   433         const TDesC8& aMessage
       
   434         )
       
   435     {
       
   436     C_TRACE( ( _T( "DISIUserChannel::ReceiveMsg 0x%x 0x%x 0x%x>" ), this, &aMessage, iObjId ) );
       
   437     // Can only be called from thread context.
       
   438     ASSERT_THREAD_CONTEXT_ALWAYS( ( EISIUserChannelfNotThreadContext3 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   439     iRx->Add( aMessage );
       
   440     iEmptyRxQueueDfc->Enque();
       
   441     C_TRACE( ( _T( "DISIUserChannel::ReceiveMsg 0x%x 0x%x 0x%x<" ), this, &aMessage, iObjId ) );
       
   442     }
       
   443 
       
   444 DISIUserChannel::DISIUserAsyncRequests::DISIUserAsyncRequests(
       
   445         const TInt aSize
       
   446         )
       
   447     {
       
   448     C_TRACE( ( _T( "DISIUserAsyncRequests::DISIUserAsyncRequests size %d>" ), aSize ) );
       
   449     iRequestLock = new NFastMutex();
       
   450     C_TRACE( ( _T( "DISIUserAsyncRequests::DISIUserAsyncRequests<" ) ) );
       
   451     }
       
   452 
       
   453 DISIUserChannel::DISIUserAsyncRequests::~DISIUserAsyncRequests()
       
   454     {
       
   455 
       
   456     C_TRACE( ( _T( "DISIUserAsyncRequests::~DISIUserAsyncRequests>" ) ) );
       
   457     iRequestCompletedList.Close();
       
   458     delete iRequestLock;
       
   459     C_TRACE( ( _T( "DISIUserAsyncRequests::~DISIUserAsyncRequests<" ) ) );
       
   460 
       
   461     }
       
   462 
       
   463 TBool DISIUserChannel::DISIUserAsyncRequests::IsPending(
       
   464         const TUint aRequest
       
   465         )
       
   466     {
       
   467     C_TRACE( ( _T( "DISIUserAsyncRequests::IsPending %d>" ), aRequest ) );
       
   468     ASSERT_RESET_ALWAYS( ( EISILastAsyncRequest > aRequest && EISIAsyncReceive <= aRequest ), ( EISIUserChannelReqOverTheLimits | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   469     TBool ret( EFalse );
       
   470     NKern::FMWait( iRequestLock );
       
   471     ret = ( iRequestStatusList[ aRequest ] ) ? ETrue : EFalse;
       
   472     NKern::FMSignal( iRequestLock );
       
   473     C_TRACE( ( _T( "DISIUserAsyncRequests::IsPending %d %d<" ), aRequest, ret ) );
       
   474     return ret;
       
   475     }
       
   476 
       
   477 void DISIUserChannel::DISIUserAsyncRequests::SetPending(
       
   478         const TUint aRequest,
       
   479         TRequestStatus* aStatus
       
   480         )
       
   481     {
       
   482     C_TRACE( ( _T( "DISIUserAsyncRequests::SetPending %d 0x%x>" ), aRequest, aStatus ) );
       
   483     ASSERT_RESET_ALWAYS( aRequest, ( EISIUserChannelNullParam | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   484     ASSERT_RESET_ALWAYS( aStatus, ( EISIUserChannelNullParam | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   485     ASSERT_RESET_ALWAYS( ( EISILastAsyncRequest > aRequest && EISIAsyncReceive <= aRequest ), ( EISIUserChannelReqOverTheLimits | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   486     // Note asserts must be done before holding the lock.
       
   487     NKern::FMWait( iRequestLock );
       
   488     iRequestStatusList[ aRequest ] = aStatus;
       
   489     NKern::FMSignal( iRequestLock );
       
   490     C_TRACE( ( _T( "DISIUserAsyncRequests::SetPending %d 0x%x<" ), aRequest, aStatus ) );
       
   491     }
       
   492 
       
   493 void DISIUserChannel::EmptyRxQueueDfc(
       
   494         TAny* aPtr // Pointer to self
       
   495         )
       
   496     {
       
   497    	C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc>" ) ) );
       
   498     DISIUserChannel& chTmp = *reinterpret_cast<DISIUserChannel*>( aPtr );
       
   499     C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc 0x%x 0x%x>" ), &chTmp, chTmp.iObjId ) );
       
   500     if( chTmp.iRequests->IsPending( EISIAsyncReceive ) && ( chTmp.iRx->Count() > 0 ) )
       
   501         {
       
   502         TDes8& tmpDes = chTmp.iRx->Get();
       
   503         TInt desMaxLen( Kern::ThreadGetDesMaxLength( chTmp.iThread, chTmp.iReceiveBufPtr ) );
       
   504         // If user descriptor legth is enough and length get not failed.
       
   505         if( desMaxLen >= tmpDes.Length() )
       
   506             {
       
   507             // Write to user address space (iReceiveBufPtr) the content of tmpDes starting from zero offset as 8bit descriptor data.
       
   508             TInt writeError( Kern::ThreadDesWrite( chTmp.iThread, chTmp.iReceiveBufPtr, tmpDes, KDestStartOffset, KChunkShiftBy0, chTmp.iThread ) );
       
   509             if( writeError == KErrNone )
       
   510                 {
       
   511                 C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc write 0x%x k->u 0x%x ok" ), &tmpDes, chTmp.iReceiveBufPtr ) );
       
   512                 chTmp.EnqueChannelRequestCompleteDfc( EISIAsyncReceive, writeError );
       
   513                 MemApi::DeallocBlock( tmpDes );
       
   514                 }
       
   515             // Write unsuccesfull don't deallocate the block.
       
   516             else
       
   517                 {
       
   518                 C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc write 0x%x k->u 0x%x NOK, reason %d" ), &tmpDes, chTmp.iReceiveBufPtr, writeError ) );
       
   519                 TRACE_ASSERT_INFO( 0, chTmp.iObjId << KObjIdShift | (TUint16)writeError );
       
   520                 // Roll the message back to que.
       
   521                 chTmp.iRx->RollBack( tmpDes );
       
   522                 chTmp.EnqueChannelRequestCompleteDfc( EISIAsyncReceive, writeError );
       
   523                 }
       
   524             }
       
   525         // If descriptor invalid.
       
   526         else
       
   527             {
       
   528             TRACE_WARNING( 0, chTmp.iObjId << KObjIdShift | (TUint16)tmpDes.Length() );
       
   529             // Roll the message back to que.
       
   530             chTmp.iRx->RollBack( tmpDes );
       
   531             // If invalid content.
       
   532             if( KErrBadDescriptor == desMaxLen )
       
   533                 {
       
   534                 TRACE_ASSERT_INFO( 0, chTmp.iObjId << KObjIdShift | (TUint16)desMaxLen );
       
   535                 C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc invalid descriptor 0x%x" ), chTmp.iObjId ) );
       
   536                 chTmp.EnqueChannelRequestCompleteDfc( EISIAsyncReceive, KErrBadDescriptor );
       
   537                 }
       
   538             // If length too small (if other assert).
       
   539             else
       
   540                 {
       
   541                 TUint16 neededLength( tmpDes.Length() );
       
   542                 TRACE_WARNING( 0, chTmp.iObjId << KObjIdShift | (TUint16)desMaxLen );
       
   543                 C_TRACE( ( _T( "DISAUserChannel::EmptyRxQueueDfc descriptor length too small length %d needed %d" ), desMaxLen, neededLength ) );
       
   544                 ASSERT_RESET_ALWAYS( KErrNone == Kern::ThreadRawWrite( chTmp.iThread, chTmp.iNeededBufLen, &neededLength, sizeof(TUint16), chTmp.iThread ), 
       
   545                                         EISIUserChannelDesWriteFailed | chTmp.iObjId << KObjIdShift | EDISIUserChannelTraceId << KClassIdentifierShift );
       
   546                 chTmp.EnqueChannelRequestCompleteDfc( EISIAsyncReceive, KErrOverflow );
       
   547                 }
       
   548             }
       
   549         }
       
   550     else
       
   551         {
       
   552         C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc no receive active or no message" ) ) );
       
   553         }
       
   554     C_TRACE( ( _T( "DISIUserChannel::EmptyRxQueueDfc 0x%x<" ), chTmp.iObjId ) );
       
   555     }
       
   556 
       
   557 // called in router ext context
       
   558 void DISIUserChannel::EnqueChannelRequestCompleteDfc(
       
   559         TInt aRequest,
       
   560         TInt aStatusToComplete
       
   561         )
       
   562     {
       
   563     C_TRACE( ( _T( "DISIUserChannel::EnqueChannelRequestCompleteDfc 0x%x %d %d 0x%x>" ), this, aRequest, aStatusToComplete, iObjId ) );
       
   564     ASSERT_THREAD_CONTEXT_ALWAYS( ( EISIUserChannelfNotThreadContext | EDISIUserChannelTraceId << KClassIdentifierShift ) );    
       
   565     //TODO check the error code
       
   566     iRequests->iRequestCompletedList.Append( aRequest ); 
       
   567     iRequests->iRequestCompletionValueList[ aRequest ] = aStatusToComplete;
       
   568     iCompleteChannelRequestDfc->Enque();
       
   569     C_TRACE( ( _T( "DISIUserChannel::EnqueChannelRequestCompleteDfc 0x%x %d %d 0x%x<" ), this, aRequest, aStatusToComplete, iObjId ) );
       
   570     }
       
   571 
       
   572 // Run in ISI user channel kernel thread context.
       
   573 void DISIUserChannel::CompleteChannelRequestDfc(
       
   574         TAny* aPtr
       
   575         )
       
   576     {
       
   577     C_TRACE( ( _T( "DISIUserChannel::CompleteChReqDfc>" ) ) );
       
   578     // Make sure that user side is accessed only by ldd DFCThread.
       
   579     ASSERT_THREAD_CONTEXT_ALWAYS( ( EISIUserChannelfNotThreadContext2 | EDISIUserChannelTraceId << KClassIdentifierShift ) );
       
   580     DISIUserChannel* chPtr = reinterpret_cast<DISIUserChannel*>( aPtr );
       
   581     C_TRACE( ( _T( "DISIUserChannel::CompleteChReqDfc 0x%x 0x%x" ), chPtr, chPtr->iObjId ) );
       
   582     TInt request = chPtr->iRequests->iRequestCompletedList[ KFirstRequest ];
       
   583     TRequestStatus* status( chPtr->iRequests->iRequestStatusList[ request ] );
       
   584     Kern::RequestComplete( chPtr->iThread, status, chPtr->iRequests->iRequestCompletionValueList[ request ] );
       
   585     chPtr->iRequests->iRequestCompletedList.Remove( KFirstRequest );
       
   586     chPtr->iRequests->iRequestStatusList[ request ] = NULL;
       
   587     chPtr->iRequests->iRequestCompletionValueList[ request ] = KNotInitializedStatus;
       
   588     
       
   589     if( chPtr->iRequests->iRequestCompletedList.Count() != 0 )
       
   590         {
       
   591         CompleteChannelRequestDfc( chPtr );
       
   592         }
       
   593     C_TRACE( ( _T( "DISIUserChannel::CompleteChReqDfc 0x%x 0x%x<" ), chPtr, chPtr->iObjId ) );
       
   594     }