connectivitylayer/isce/isirouter_dll/src/isicltransceiver.cpp
author mikaruus <mika.a.ruuskanen@nokia.com>
Wed, 17 Feb 2010 13:58:55 +0200
changeset 7 fa67e03b87df
parent 5 8ccc39f9d787
child 9 8486d82aef45
permissions -rw-r--r--
New release based on our 2010wk08 release

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/



#include <kernel.h>               // For Kern
#include "isirouter.h"            // For DISIRouter
#include "isiroutertrace.h"       // For C_TRACE, ASSERT_RESET.. and fault codes
#include "misirouterlinkif.h"     // For MISIRouterLinkIf
#include "isihelpers.h"           // For GET_SENDER_DEV...
#include "memapi.h"               // For MemApi
#include <trxdefs.h>              // For ETrxTest...
#include "isicltransceiver.h"     // For DISICLTransceiver
#include <nsisi.h>                // For PN_NAMESERVICE... TODO:Remove this

#define PN_MEDIA_TEST 0xBB //not real
//#define PN_DEV_MODEM 0x12
#define PN_DEV_DUMMYIST 0x13
#define PN_DEV_OWN 0x6C

// CONSTS
DISICLTransceiver* DISICLTransceiver::iThisPtr = NULL;


// Faults
enum TISICLTransceiverFaults
    {
    EISICLTransceiverMemAllocFailure = 0x01,
    EISICLTransceiverMemAllocFailure1,
    EISICLTransceiverNotSupportedMedia,
    EISICLTransceiverOverTheLimits,
    EISICLTransceiverNULLPtr,
    EISICLTransceiverNotSupportedDevice,
    };

DISICLTransceiver::DISICLTransceiver( DISIRouter* aPtr )
    : iRouter( aPtr )
    {
    C_TRACE( ( _T( "DISICLTransceiver::DISICLTransceiver>" ) ) );
    iLinksArray = new MISIRouterLinkIf*[ EISIAmountOfMedias ];
    ASSERT_RESET_ALWAYS( iLinksArray, ( EISICLTransceiverMemAllocFailure | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
    // Initialize links
    for( TInt i( 0 ); i < EISIAmountOfMedias; i++ )
        {
        iLinksArray[ i ] = NULL;
        }
    //TODO add real media and trx when known
    iLinksArray[ EISIMediaTest ] = MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_TEST, ETrxTest );
    C_TRACE( ( _T( "DISICLTransceiver::DISICLTransceiver<" ) ) );
    }

DISICLTransceiver::~DISICLTransceiver()
    {
    C_TRACE( ( _T( "DISICLTransceiver::~DISICLTransceiver>" ) ) );
    for( TUint8 i( 0 ); i < EISIAmountOfMedias; i++ )
        {
        MISIRouterLinkIf* tmp = iLinksArray[ i ];
        if( tmp )
            {
            tmp->Release();
            tmp = NULL;
            iLinksArray[ i ] = NULL;
            }
        }
    delete []iLinksArray;
    C_TRACE( ( _T( "DISICLTransceiver::~DISICLTransceiver<" ) ) );
    }

TInt DISICLTransceiver::SendCommIsaEntityNotReachableResp( TDes8& aMessage )
    {
    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x>" ), &aMessage ) );
    const TUint8* msgTmpPtr( aMessage.Ptr() );
    TInt error = KErrAlreadyExists;

    // To avoid COMM_ISA_ENTITY_NOT_REACHABLE_RESP loop
    if( msgTmpPtr[ ISI_HEADER_OFFSET_MESSAGEID ] != COMMON_MESSAGE &&
        msgTmpPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] != COMM_ISA_ENTITY_NOT_REACHABLE_RESP )
        {
        // Make channel opening request followinfg COMM specification: 000.026
        // Length is sixteen bytes.
		    TUint8 length( 16 );
		    TDes8& tempPtr = MemApi::AllocBlock( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
		    ASSERT_RESET_ALWAYS( &tempPtr, ( EISICLTransceiverMemAllocFailure1 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
  	    ASSERT_RESET_ALWAYS( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP > ISI_HEADER_OFFSET_MESSAGEID, ( EISICLTransceiverOverTheLimits | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
  	    TUint8* ptr = const_cast<TUint8*>( tempPtr.Ptr() );
  	    // We start to append from transaction id.
  	    tempPtr.SetLength( ISI_HEADER_OFFSET_TRANSID );
  	    // Get the header until messageid from prev. message.
		    // Just turn receiver and sender device and object vice versa.
		    ptr[ ISI_HEADER_OFFSET_MEDIA ] = msgTmpPtr[ ISI_HEADER_OFFSET_MEDIA ];
		    SET_RECEIVER_DEV( ptr, GET_SENDER_DEV( aMessage ) );
		    SET_SENDER_DEV  ( ptr, GET_RECEIVER_DEV( aMessage ) );
		    ptr[ ISI_HEADER_OFFSET_RESOURCEID ] = msgTmpPtr[ ISI_HEADER_OFFSET_RESOURCEID ];
		    SET_LENGTH( ptr, length - PN_HEADER_SIZE );
		    SET_RECEIVER_OBJ( ptr, GET_SENDER_OBJ( aMessage ) );
		    SET_SENDER_OBJ( ptr, GET_RECEIVER_OBJ( aMessage ) );
		    // Transactionid. Set to 0x01 since this is the first.
		    tempPtr.Append( msgTmpPtr[ ISI_HEADER_OFFSET_TRANSID ] );
		    // Message ID
		    tempPtr.Append( ISI_HEADER_OFFSET_MESSAGEID );
		    // Sub message ID.
		    tempPtr.Append( COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
		    // Not Delivered Message from original req.
		    tempPtr.Append( msgTmpPtr[ ISI_HEADER_OFFSET_MESSAGEID ] );
		    // Status - COMM_ISA_ENTITY_NOT_AVAILABLE
		    tempPtr.Append( 0x00 );
		    // Filler
		    tempPtr.Append( 0x00 );
		    // Filler
		    tempPtr.Append( 0x00 );
		    // Filler
            tempPtr.Append( 0x00 );
            error = RouteISIMessage( tempPtr );
   		    }
		else
		    {
		    C_TRACE( ( _T( "DISICLTransceiver Not sending another CommIsaEntityNotReachableResp" ) ) );
		    }
    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x<" ), &aMessage ) );
    return error;
    }

TInt DISICLTransceiver::RouteISIMessage( TDes8& aMessage )
    {
	 C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x>" ), &aMessage ) );
	TInt error( ValidateISIMessage( aMessage ) );
    TBool sendOk( EFalse );
    if(GET_RECEIVER_DEV( aMessage ) == PN_DEV_OWN )
        {
        C_TRACE( ( _T( "DISIRouter msg to PN_DEV_APE" ) ) );
        sendOk = iRouter->Receive( aMessage, GET_RECEIVER_OBJ( aMessage ) );
        C_TRACE( ( _T( "DISIRouter router sendOk %d" ), sendOk ) );
        }
    else
        {
         C_TRACE( ( _T( "DISIRouter msg to other device" ) ) );
         TUint8 linkId = MapDeviceToMedia( GET_RECEIVER_DEV( aMessage ) );
	       ASSERT_RESET_ALWAYS( linkId < EISIAmountOfMedias, ( EISICLTransceiverNotSupportedMedia | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
         MISIRouterLinkIf* link = iLinksArray[ linkId ];
         ASSERT_RESET_ALWAYS( link, ( EISICLTransceiverNULLPtr | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
         sendOk = link->Send( aMessage );
         C_TRACE( ( _T( "DISIRouter link sendOk %d" ), sendOk ) );
         }   
    if( !sendOk )
        {
        SendCommIsaEntityNotReachableResp( aMessage );
        MemApi::DeallocBlock( aMessage );
        }
	  C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x<" ), &aMessage ) );
    return error;
    }

// KErrBadDescriptor, if message length too small
// KErrUnderFlow, if message length too big.
// KErrCouldNotConnect, if receiver object is out of scope.
TInt DISICLTransceiver::ValidateISIMessage(
        TDes8& aMessage
        )
    {
    C_TRACE( ( _T( "DISICLTransceiver::ValidateISIMessage 0x%x>" ), &aMessage ) );
    const TUint16 descLength( aMessage.Length() );
    TInt msgOk( KErrNone );
    msgOk = ( ISI_HEADER_OFFSET_MESSAGEID >= descLength ) ? KErrBadDescriptor : msgOk;
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    // Get ISI message length after known that the descriptor is big enough.
    const TUint8* msgPtr( aMessage.Ptr() );
    const TUint16 isiMsgLength( GET_LENGTH( msgPtr ) + PN_HEADER_SIZE );
    // If the descriptor length is less than ISI message length.
    msgOk = ( ( msgOk == KErrNone && isiMsgLength > descLength ) ? KErrUnderflow : msgOk );
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    // If the ISI message length is bigger that the largest supported.
    msgOk = ( ( msgOk == KErrNone && isiMsgLength > KMaxISIMsgSize ) ? KErrUnderflow : msgOk );
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    // If the ISI message length with PN_HEADER_SIZE is less or equal than ISI_HEADER_OFFSET_MESSAGEID.
    msgOk = ( ( msgOk == KErrNone && isiMsgLength <= ISI_HEADER_OFFSET_MESSAGEID ) ? KErrUnderflow : msgOk );
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    TRACE_ASSERT_INFO( msgOk == KErrNone, isiMsgLength );
    TRACE_ASSERT_INFO( msgOk == KErrNone, descLength );
    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
    C_TRACE( ( _T( "DISICLTransceiver::ValidateISIMessage %d<" ), msgOk ) );
    return msgOk;
    }

TUint8 DISICLTransceiver::MapDeviceToMedia(
        const TUint8 aDevice
        )
    {
    C_TRACE( ( _T( "DISICLTransceiver::MapDeviceToMedia aDevice %d>" ), aDevice ) );
    TUint8 media( KErrNone );
    switch( aDevice )
        {
        case PN_DEV_MODEM:
            {
            media = EISIMediaSharedMemory;
            break;
            }
        case PN_DEV_DUMMYIST:
            {
            media = EISIMediaTest;
            break;
            }
        // Not supported device
        default:
            {
           	ASSERT_RESET_ALWAYS( 0, ( EISICLTransceiverNotSupportedDevice | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
            break;
            }
        }
    C_TRACE( ( _T( "DISICLTransceiver::MapDeviceToMedia media %d<" ), media ) );
    return media;
    }