/*
* Copyright (c) 2009-2010 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 "bcatoisc.h"
#include "bcatoisctrace.h"
#include "iscdefinitions.h"
#include <cdbcols.h>
#include <nsisi.h>
#include <pipeisi.h>
#include <pn_const.h>
#include <iscnokiadefinitions.h>
#include "pep_bca_types.h"
const TUint8 KDataLength = 7;
const TUint8 KStatusIndex = 0;
const TUint8 KDevIdIndex = 5;
const TUint8 KObjIdIndex = 6;
const TUint8 KPadding = 0;
const TUint KDefaultReceiveBufferSize = 2048;
using namespace BasebandChannelAdaptation;
/**
* Utility function to complete a pending request and NULL request pointer.
*/
static void CompleteRequest(TRequestStatus* &aReqStatus, const TInt aError)
{
if(( aReqStatus ) &&
( *aReqStatus == KRequestPending ))
{
// Only realy need to trace if we actually complete the request.
C_TRACE( (_T("CompleteRequest completing client request with aError %d ->"), aError ) );
//Complete clients request
User::RequestComplete( aReqStatus, aError );
aReqStatus = NULL;
}
}
/**
* Default constructor to create a CNotifyFlowControlMonitor instance.
*/
CNotifyFlowControlMonitor::CNotifyFlowControlMonitor(RIscApi& aIscApi)
:CActive(EPriorityHigh),
iIscApi(aIscApi),
iWriteStatus(NULL)
{
C_TRACE( (_T("CNotifyFlowControlMonitor::CNotifyFlowControlMonitor RIscApi 0x%x ->"), &aIscApi ) );
CActiveScheduler::Add(this);
C_TRACE( (_T("CNotifyFlowControlMonitor::CNotifyFlowControlMonitor <-") ) );
}
void CNotifyFlowControlMonitor::NotifyFlowControlStatus()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::NotifyFlowControlStatus() ->") ) );
ASSERT(!IsActive());
iFlowControlValue = iIscApi.FlowControlStatus();
C_TRACE( (_T("CNotifyFlowControlMonitor::NotifyFlowControlStatus initial iFlowControlValue %d ->"), iFlowControlValue ) );
iIscApi.NotifyFlowControl(iStatus, iFlowControlValue);
SetActive();
C_TRACE( (_T("CNotifyFlowControlMonitor::NotifyFlowControlStatus() <-") ) );
}
void CNotifyFlowControlMonitor::RequestFlowcontrolChange( TRequestStatus& aStatus )
{
C_TRACE( (_T("CNotifyFlowControlMonitor::RequestFlowcontrolChange ->") ) );
iWriteStatus = &aStatus;
*iWriteStatus = KRequestPending;
C_TRACE( (_T("CNotifyFlowControlMonitor::RequestFlowcontrolChange <-") ) );
}
void CNotifyFlowControlMonitor::CompleteFlowcontrolChangeWithCancel()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::CompleteFlowcontrolChangeWithCancel() ->") ) );
// If pending request, complete as cancelled
CompleteRequest(iWriteStatus, KErrCancel);
C_TRACE( (_T("CNotifyFlowControlMonitor::CompleteFlowcontrolChangeWithCancel() <-") ) );
}
void CNotifyFlowControlMonitor::RunL()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::RunL() iStatus %d ->"), iStatus.Int() ) );
ASSERT( iStatus.Int() == KErrNone);
iFlowControlValue = iIscApi.FlowControlStatus();
C_TRACE( (_T("CNotifyFlowControlMonitor::RunL flow control Value has changed and is now: (%d)"), iFlowControlValue ) );
if( iFlowControlValue == EIscFlowControlOff)
{
// If pending request, complete it as flow control is now OFF
CompleteRequest(iWriteStatus,KErrNone);
}
//Check for further flow control status changes
iIscApi.NotifyFlowControl(iStatus, iFlowControlValue);
SetActive();
C_TRACE( (_T("CNotifyFlowControlMonitor::RunL() <-") ) );
}
TInt CNotifyFlowControlMonitor::GetFlowControlState()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::GetFlowControlState() flowcontrol value %d <->"), iFlowControlValue ) );
return iFlowControlValue;
}
void CNotifyFlowControlMonitor::DoCancel()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::DoCancel() ->") ) );
// If pending request, complete it as cancelled
CompleteRequest(iWriteStatus, KErrCancel);
C_TRACE( (_T("CNotifyFlowControlMonitor::DoCancel() req is completed") ) );
iIscApi.NotifyFlowControlCancel();
C_TRACE( (_T("CNotifyFlowControlMonitor::DoCancel() <-") ) );
}
CNotifyFlowControlMonitor::~CNotifyFlowControlMonitor()
{
C_TRACE( (_T("CNotifyFlowControlMonitor::~CNotifyFlowControlMonitor() ->") ) );
Cancel();
C_TRACE( (_T("CNotifyFlowControlMonitor::~CNotifyFlowControlMonitor() <-") ) );
}
CNotifyWriteStatusMonitor::CNotifyWriteStatusMonitor( CBcaToIsc& aUser, RIscApi& aIscApi )
:CActive(EPriorityStandard),
iUser(aUser),
iIscApi(aIscApi)
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::CNotifyWriteStatusMonitor ->") ) );
CActiveScheduler::Add(this);
C_TRACE( (_T("CNotifyWriteStatusMonitor::CNotifyWriteStatusMonitor <-") ) );
}
void CNotifyWriteStatusMonitor::Write( TRequestStatus& aStatus, const TDesC8& aBuf )
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::Write ->") ) );
iBuf = &aBuf;
iClientStatus = &aStatus;
*iClientStatus = KRequestPending;
if( iUser.iFlowControlMonitor->GetFlowControlState() == EIscFlowControlOff )
{
SendAndComplete(KErrNone);
}
else //flow control on
{
iUser.iFlowControlMonitor->RequestFlowcontrolChange( iStatus );
SetActive();
}
C_TRACE( (_T("CNotifyWriteStatusMonitor::Write <-") ) );
}
void CNotifyWriteStatusMonitor::RunL()
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::RunL() iStatus %d ->"), iStatus.Int() ) );
// KARI ei kutsu IASC apin data sendiä jos erksa OK?
SendAndComplete(iStatus.Int());
C_TRACE( (_T("CNotifyWriteStatusMonitor::RunL() <-") ) );
}
void CNotifyWriteStatusMonitor::SendAndComplete(TInt aError)
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::SendAndComplete() ->")));
// We may have had the request cancelled, in which case do not send the write data
if (aError == KErrNone)
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::SendAndComplete() iIscApi.DataSend ")));
aError = iIscApi.DataSend( *iBuf );
}
// If pending request, complete it as specified by the error status
// This could be OK or canncelled
CompleteRequest(iClientStatus, aError);
C_TRACE( (_T("CNotifyWriteStatusMonitor::SendAndComplete() <-") ) );
}
void CNotifyWriteStatusMonitor::DoCancel()
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::DoCancel() ->") ) );
iUser.iFlowControlMonitor->CompleteFlowcontrolChangeWithCancel();
// If pending request, complete it as cancelled
CompleteRequest(iClientStatus, KErrCancel);
C_TRACE( (_T("CNotifyWriteStatusMonitor::DoCancel() <-") ) );
}
CNotifyWriteStatusMonitor::~CNotifyWriteStatusMonitor()
{
C_TRACE( (_T("CNotifyWriteStatusMonitor::~CNotifyWriteStatusMonitor() ->") ) );
Cancel();
C_TRACE( (_T("CNotifyWriteStatusMonitor::~CNotifyWriteStatusMonitor() <-") ) );
}
/**
* Default constructor to create a CBcaToIsc instance.
*/
CBcaToIsc::CBcaToIsc() :
CActive( EPriorityStandard ),
iMessageBufferPtr( 0,0 ),
iReadLength(0),
iChannelNumber( 0xffff )
{
C_TRACE( (_T("CBcaToIsc::CBcaToIsc() ->") ) );
C_TRACE( (_T("CBcaToIsc::CBcaToIsc() <-") ) );
}
/**
2nd phase of construction: allocates member objects
@leave when members cannot be constructed. */
void CBcaToIsc::ConstructL()
{
C_TRACE( (_T("CBcaToIsc::ConstructL() ->") ) );
__ASSERT_DEBUG(!iFlowControlMonitor, User::Panic(_L("BcaToIsc.dll"), EMonitorAlreadyExists));
__ASSERT_DEBUG(!iWriteStatusMonitor, User::Panic(_L("BcaToIsc.dll"), EMonitorAlreadyExists));
iFlowControlMonitor = new (ELeave)CNotifyFlowControlMonitor(iIscApi);
iWriteStatusMonitor = new (ELeave)CNotifyWriteStatusMonitor(*this, iIscApi);
iReceivedMessageBuffer = HBufC8::NewL(KDefaultReceiveBufferSize);
iMessageBufferPtr.Set( iReceivedMessageBuffer->Des() );
iMessageBufferPtr.FillZ();
iChannelList.Append( EIscNokiaNifPep5 );
iChannelList.Append( EIscNokiaNifPep6 );
iChannelList.Append( EIscNokiaNifPep7 );
iChannelList.Append( EIscNokiaNifPep8 );
CActiveScheduler::Add( this );
C_TRACE( (_T("CBcaToIsc::ConstructL() this 0x%x <-"), this ) );
}
/**
* Destructor
*/
CBcaToIsc::~CBcaToIsc()
{
C_TRACE( (_T("CBcaToIsc::~CBcaToIsc() ->") ) );
if( iFlowControlMonitor )
{
delete iFlowControlMonitor;
}
if( iWriteStatusMonitor )
{
delete iWriteStatusMonitor;
}
if( iReceivedMessageBuffer )
{
delete iReceivedMessageBuffer;
}
iClientShutdownStatus = NULL;
iClientOpenStatus = NULL;
C_TRACE( (_T("CBcaToIsc::~CBcaToIsc() <-") ) );
}
// remove loan / returnloan deadcode from lower layers
/** This method deletes the BCA itself.*/
void CBcaToIsc::Release()
{
C_TRACE( (_T("CBcaToIsc::Release() this 0x%x ->"), this ) );
delete this;
C_TRACE( (_T("CBcaToIsc::Release() this 0x%x <-"), this ) );
}
/**
* Informs that the BCA is required by the client(for instance, Raw IP NIF).
* @param aStatus complete status, KErrNone if successful, error code otherwise.
* @param aChannelId comm port name.
*/
void CBcaToIsc::Open(TRequestStatus& aStatus, const TDesC& aChannelId)
{
C_TRACE( (_T("CBcaToIsc::Open aStatus %d aChannelId descriptor %S ->"), aStatus.Int(), &aChannelId ) );
iClientOpenStatus = &aStatus;
*iClientOpenStatus = KRequestPending;
// Expected form either <XXX>Int_<XX> (i.e. 100Int_3) or Int!!!
TUint16 channelid( 0xffff );
TInt error( KErrGeneral );
_LIT(KIntUnderScore, "Int_");
TInt len1 = aChannelId.Find(KIntUnderScore);
if( len1 < KErrNone )
{
// Int format
TLex16 channelParser(aChannelId);
error = channelParser.Val(channelid, EDecimal);
}
else
{
// <XXX>Int_<XX> format
TUint numPos = len1 + KIntUnderScore.iTypeLength;
TPtrC digit = aChannelId.Mid(numPos);
TLex16 channelParser(digit);
error = channelParser.Val(channelid, EDecimal);
}
ASSERT( KErrNone == error );
C_TRACE( (_T("CBcaToIsc::Open parsed channel id: 0x%x"), channelid ) );
if( error == KErrNone )
{
TInt index( 0 );
TBool channelOpened( EFalse );
TRequestStatus status( KRequestPending );
for( index = 0; index < iChannelList.Length(); index++ )
{
status = KRequestPending;
iIscApi.Open( iChannelList[index], status, EOwnerThread );
User::WaitForRequest( status );
if( KErrNone == status.Int() )
{
C_TRACE( (_T("CBcaToIsc::Open channel 0x%x opened"), iChannelList[index] ) );
channelOpened = ETrue;
break;
}
}
if( !channelOpened )
{
C_TRACE( (_T("CBcaToIsc::Open channel opening failed") ) );
User::RequestComplete( iClientOpenStatus, KErrGeneral );
iClientOpenStatus = NULL;
}
else if( KErrNone == SendNameAddReq( iChannelList[index], channelid ) )
{
iFlowControlMonitor->NotifyFlowControlStatus();
iChannelNumber = status.Int() == KErrNone ? iChannelList[index] : iChannelNumber;
iMessageBufferPtr.SetLength( 0 );
iStatus = KRequestPending;
iIscApi.Receive( iStatus, iMessageBufferPtr, iReadLength );
SetActive();
}
else
{
C_TRACE( (_T("CBcaToIsc::Open sending of PNS_NAME_ADD_REQ failed") ) );
iIscApi.Close();
User::RequestComplete( iClientOpenStatus, KErrGeneral );
iClientOpenStatus = NULL;
}
}
else
{
User::RequestComplete( iClientOpenStatus, error );
iClientOpenStatus = NULL;
}
C_TRACE( (_T("CBcaToIsc::Open <-") ) );
}
/**
Shuts the BCA channel down in a graceful manner. BCA releases its resources.
Cancels all outstanding operations: Writes, Reads and Ioctls.
@param aStatus completion status: Always KErrNone.
*/
void CBcaToIsc::Shutdown(TRequestStatus& aStatus)
{
C_TRACE( (_T("CBcaToIsc::Shutdown aStatus %d ->"), aStatus.Int() ) );
iClientShutdownStatus = &aStatus;
*iClientShutdownStatus = KRequestPending;
iWriteStatusMonitor->Cancel();
iFlowControlMonitor->Cancel();
iIscApi.DataReceiveCancel();
if( KErrNone == SendNameRemoveReq() )
{
iMessageBufferPtr.SetLength( 0 );
iStatus = KRequestPending;
iIscApi.Receive( iStatus, iMessageBufferPtr, iReadLength );
SetActive();
}
else
{
C_TRACE( (_T("CBcaToIsc::Shutdown sending of PNS_NAME_REMOVE_REQ failed") ) );
iIscApi.Close();
User::RequestComplete(iClientShutdownStatus, KErrGeneral);
iClientShutdownStatus = NULL;
}
C_TRACE( (_T("CBcaToIsc::Shutdown <-") ) );
}
/**
* Closes the BCA immediately. BCA releases its resources.
* cancels all Writes, Reads and Controls.
*/
void CBcaToIsc::Close()
{
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x->"), iChannelNumber ) );
if( iClientShutdownStatus && ( *iClientShutdownStatus == KRequestPending ) )
{
C_TRACE( (_T("CBcaToIsc::Close completing client Shutdown request with KErrCancel ->") ) );
User::RequestComplete(iClientShutdownStatus, KErrCancel);
}
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x 1"), iChannelNumber ) );
iWriteStatusMonitor->Cancel();
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x 2"), iChannelNumber ) );
iFlowControlMonitor->Cancel();
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x 3"), iChannelNumber ) );
iIscApi.DataReceiveCancel();
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x 4"), iChannelNumber ) );
iIscApi.DataSendCancel();
C_TRACE( (_T("CBcaToIsc::Close() iChannelNumber=0x%x 5"), iChannelNumber ) );
iIscApi.Close();
C_TRACE( (_T("CBcaToIsc::Close() <-") ) );
}
/**
* Queues a Read.
* @param aStatus complete status, KErrNone if successful, error code otherwise.
* @param aBuf buffer for data to be read.
* @note The buffer is owned by the client. Client must not access / modify the buffer until the Read completes.
*/
void CBcaToIsc::Read(TRequestStatus& aStatus,TDes8& aBuf)
{
C_TRACE( (_T("CBcaToIsc::Read aStatus=%d aBuf=0x%x ->"), aStatus.Int(), &aBuf ) );
iIscApi.DataReceive( aStatus, aBuf, iReadLength );
C_TRACE( (_T("CBcaToIsc::Read aStatus=%d aBuf=0x%x <-"), aStatus.Int(), &aBuf ) );
}
/**
* Queues a Write
* @param aStatus the complete status, KErrNone if successful, error code otherwise.
* @param aBuf the buffer to sent.
* @note The buffer is owned by the client. Client must not access / modify the buffer until the Write completes.
*/
void CBcaToIsc::Write( TRequestStatus& aStatus, const TDesC8& aBuf )
{
C_TRACE( (_T("CBcaToIsc::Write aStatus %d aBuf %S ->"), aStatus.Int(), &aBuf ) );
iWriteStatusMonitor->Write(aStatus, aBuf);
C_TRACE( (_T("CBcaToIsc::Write <-") ) );
}
/**
Cancels the outstanding Read operation.(best effort operation: the read may have been completed already.)
*/
void CBcaToIsc::CancelRead()
{
C_TRACE( (_T("CBcaToIsc::CancelRead() ->") ) );
iIscApi.DataReceiveCancel();
C_TRACE( (_T("CBcaToIsc::CancelRead() <-") ) );
}
/**
Cancels all Write operations.(best effort attempt: the write may have been completed already.)
*/
void CBcaToIsc::CancelWrite()
{
C_TRACE( (_T("CBcaToIsc::CancelWrite() ->") ) );
iWriteStatusMonitor->Cancel();
C_TRACE( (_T("CBcaToIsc::CancelWrite() <-") ) );
}
/**
* Ioctl: asynchronously controls the BcaToIsc.
* @param aStatus complete status, KErrNone if successful, system-wide error code otherwise.
* @param aOptLevel option level to be used.
* @param aOptName option name to be used.
* @param aOpt an optional parameter,holds the option value on return or the option value to be set.
*/
void CBcaToIsc::Ioctl(
TRequestStatus& aStatus,
TUint, // aOptLevel,
TUint, // aOptName,
TDes8& // aOpt
)
{
C_TRACE( (_T("CBcaToIsc::Ioctl ->") ) );
TRequestStatus* ptrStatus = &aStatus;
User::RequestComplete( ptrStatus, KErrNotSupported);
C_TRACE( (_T("CBcaToIsc::Ioctl <-") ) );
}
/** Cancels an outstanding Ioctl, if any. */
void CBcaToIsc::CancelIoctl()
{
C_TRACE( (_T("CBcaToIsc::CancelIoctl() ->") ) );
C_TRACE( (_T("CBcaToIsc::CancelIoctl() <-") ) );
}
/**
* Sends PNS_NAME_ADD_REQ
* @param aObjId object id for the name to be added
* @return KErrNone if message sent succesfully, otherwise error code
*/
TInt CBcaToIsc::SendNameAddReq( TUint16& aObjId, TUint16& aClientObjId )
{
C_TRACE( (_T("CBcaToIsc::SendNameAddReq() ->") ) );
HBufC8* message = HBufC8::New( ISI_HEADER_SIZE + SIZE_PNS_NAME_ADD_REQ );
TInt err( KErrGeneral );
if( message )
{
TPtr8 messageptr = message->Des();
messageptr.FillZ();
// Add 32bit name (Big-endian)
iName.Append( aClientObjId );
iName.Append( PN_PEP_SUB_TYPE_SYMBIAN_INTERNAL );
iName.Append( PN_PEP_TYPE_COMMON );
iName.Append( PN_PIPE );
TUint8 nameOffset( ISI_HEADER_SIZE + PNS_NAME_ADD_REQ_OFFSET_NAMEENTRY );
TIsiSend isimessage( messageptr, ISI_HEADER_SIZE + SIZE_PNS_NAME_ADD_REQ );
isimessage.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_NAMESERVICE );
isimessage.Set8bit( ISI_HEADER_OFFSET_TRANSID, 0 );
isimessage.Set8bit( ISI_HEADER_OFFSET_MESSAGEID, PNS_NAME_ADD_REQ );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_NAME_ADD_REQ_OFFSET_RESERVED1, KPadding );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_NAME_ADD_REQ_OFFSET_RESERVED2, KPadding );
isimessage.Set8bit( nameOffset, iName[0] );
isimessage.Set8bit( nameOffset + 1, iName[1] );
isimessage.Set8bit( nameOffset + 2, iName[2] );
isimessage.Set8bit( nameOffset + 3, iName[3] );
isimessage.Set8bit( nameOffset + PN_NAME_SRV_ITEM_STR_OFFSET_DEV, THIS_DEVICE );
isimessage.Set8bit( nameOffset + PN_NAME_SRV_ITEM_STR_OFFSET_OBJ, aObjId );
isimessage.Set8bit( nameOffset + PN_NAME_SRV_ITEM_STR_OFFSET_FLAGS, PN_NAME_UNDEF );
isimessage.Set8bit( nameOffset + PN_NAME_SRV_ITEM_STR_OFFSET_RESERVED, KPadding );
isimessage.Complete();
err = iIscApi.Send( messageptr );
C_TRACE( (_T("CBcaToIsc::SendNameAddReq() success: 0x%x"), err ) );
delete message;
}
else
{
C_TRACE( (_T("CBcaToIsc::SendNameAddReq() memory allocation failed") ) );
ASSERT(0);
}
C_TRACE( (_T("CBcaToIsc::SendNameAddReq() <-") ) );
return err;
}
/**
* Sends PNS_NAME_REMOVE_REQ
* @return KErrNone if message sent succesfully, otherwise error code
*/
TInt CBcaToIsc::SendNameRemoveReq()
{
C_TRACE( (_T("CBcaToIsc::SendNameRemoveReq() ->") ) );
HBufC8* message = HBufC8::New( ISI_HEADER_SIZE + SIZE_PNS_NAME_REMOVE_REQ );
TInt err( KErrGeneral );
if( message )
{
TPtr8 messageptr = message->Des();
messageptr.FillZ();
TUint8 nameOffset( ISI_HEADER_SIZE + PNS_NAME_REMOVE_REQ_OFFSET_NAME );
TIsiSend isimessage( messageptr, ISI_HEADER_SIZE + SIZE_PNS_NAME_REMOVE_REQ );
isimessage.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_NAMESERVICE );
isimessage.Set8bit( ISI_HEADER_OFFSET_TRANSID , 0 );
isimessage.Set8bit( ISI_HEADER_OFFSET_MESSAGEID, PNS_NAME_REMOVE_REQ );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_NAME_REMOVE_REQ_OFFSET_RESERVED1, KPadding );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_NAME_REMOVE_REQ_OFFSET_RESERVED2, KPadding );
isimessage.Set8bit( nameOffset, iName[0] );
isimessage.Set8bit( nameOffset + 1, iName[1] );
isimessage.Set8bit( nameOffset + 2, iName[2] );
isimessage.Set8bit( nameOffset + 3, iName[3] );
isimessage.Complete();
err = iIscApi.Send( messageptr );
C_TRACE( (_T("CBcaToIsc::SendNameRemoveReq() success: 0x%x"), err ) );
delete message;
}
else
{
C_TRACE( (_T("CBcaToIsc::SendNameRemoveReq() memory allocation failed") ) );
ASSERT(0);
}
C_TRACE( (_T("CBcaToIsc::SendNameRemoveReq() <-") ) );
return err;
}
/**
* Sends PNS_PEP_CTRL_RESP
* @return KErrNone if message sent succesfully, otherwise error code
*/
TInt CBcaToIsc::SendPepCtrlResp(
TUint8 aTrId,
TUint8 aReceiverDev,
TUint8 aReceiverObj,
TUint8 aPipeHandle,
TUint8 aPepCtrlId,
TUint8 aPepType,
TUint8 aResult )
{
C_TRACE( (_T("CBcaToIsc::SendPepCtrlResp() ->") ) );
HBufC8* message = HBufC8::New( ISI_HEADER_SIZE + SIZE_PNS_PEP_CTRL_RESP );
TInt err( KErrGeneral );
if( message )
{
TPtr8 messageptr = message->Des();
messageptr.FillZ();
TIsiSend isimessage( messageptr, ISI_HEADER_SIZE + SIZE_PNS_PEP_CTRL_RESP );
isimessage.Set8bit( ISI_HEADER_OFFSET_RECEIVERDEVICE, aReceiverDev);
isimessage.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_PIPE);
isimessage.Set8bit( ISI_HEADER_OFFSET_RECEIVEROBJECT, aReceiverObj);
isimessage.Set8bit( ISI_HEADER_OFFSET_TRANSID , aTrId);
isimessage.Set8bit( ISI_HEADER_OFFSET_MESSAGEID, PNS_PEP_CTRL_RESP );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_PEP_CTRL_RESP_OFFSET_PIPEHANDLE, aPipeHandle );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_PEP_CTRL_RESP_OFFSET_PEPCTRLID, aPepCtrlId );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_PEP_CTRL_RESP_OFFSET_PEPTYPE, aPepType );
isimessage.Set8bit( ISI_HEADER_SIZE + PNS_PEP_CTRL_RESP_OFFSET_ERRORCODE, aResult );
isimessage.Complete();
err = iIscApi.Send( messageptr );
C_TRACE( (_T("CBcaToIsc::SendPepCtrlResp() success: 0x%x"), err ) );
delete message;
}
else
{
C_TRACE( (_T("CBcaToIsc::SendPepCtrlResp() memory allocation failed") ) );
ASSERT(0);
}
C_TRACE( (_T("CBcaToIsc::SendPepCtrlResp() <-") ) );
return err;
}
/**
* Handles received messages
* @param aObjId object id for the name to be added
* @return KErrNone if message sent succesfully, otherwise error code
*/
void CBcaToIsc::RunL()
{
C_TRACE( (_T("CBcaToIsc::RunL() ->") ) );
if ( KErrNone == iStatus.Int() )
{
HandleReceivedMsg( TIsiReceiveC( iMessageBufferPtr ) );
}
else
{
C_TRACE( (_T("CBcaToIsc::RunL() error occured: 0x%x"), iStatus.Int() ) );
ASSERT(0);
}
C_TRACE( (_T("CBcaToIsc::RunL() <-") ) );
}
/**
* Handles cancel operation for this active object
*/
void CBcaToIsc::DoCancel()
{
C_TRACE( (_T("CBcaToIsc::DoCancel() ->") ) );
iIscApi.ReceiveCancel();
C_TRACE( (_T("CBcaToIsc::DoCancel() <-") ) );
}
/**
* Handles received message
*/
void CBcaToIsc::HandleReceivedMsg( const TIsiReceiveC& aIsiMsg )
{
C_TRACE( (_T("CBcaToIsc::HandleReceivedMsg() ->") ) );
TInt resource( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_RESOURCEID ) );
switch( resource )
{
case PN_NAMESERVICE:
{
HandleNameServiceMsg( aIsiMsg );
break;
}
case PN_PIPE:
{
HandlePipeMsg( aIsiMsg );
break;
}
default:
{
C_TRACE( (_T("CBcaToIsc::HandleReceivedMsg() unknown resource 0x%x"), resource ) );
ASSERT(0);
break;
}
}
C_TRACE( (_T("CBcaToIsc::HandleReceivedMsg() <-") ) );
}
/**
* Handles received messages from resource PN_NAME
*/
void CBcaToIsc::HandleNameServiceMsg( const TIsiReceiveC& aIsiMsg )
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() ->") ) );
TInt msgId( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_MESSAGEID ) );
switch( msgId )
{
case PNS_NAME_ADD_RESP:
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() PNS_NAME_ADD_RESP") ) );
TUint8 reason( aIsiMsg.Get8bit(
ISI_HEADER_SIZE + PNS_NAME_ADD_RESP_OFFSET_REASON ) );
if( PN_NAME_OK != reason )
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() Name adding failed: 0x%x"), reason ) );
if( iClientOpenStatus )
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() completing open") ) );
User::RequestComplete( iClientOpenStatus, KErrGeneral );
iClientOpenStatus = NULL;
iIscApi.Close();
}
// no else
}
else
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() Name added succesfully") ) );
iMessageBufferPtr.SetLength( 0 );
iStatus = KRequestPending;
iIscApi.Receive( iStatus, iMessageBufferPtr, iReadLength );
SetActive();
}
break;
}
case PNS_NAME_REMOVE_RESP:
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() PNS_NAME_REMOVE_RESP") ) );
TUint8 reason( aIsiMsg.Get8bit(
ISI_HEADER_SIZE + PNS_NAME_ADD_RESP_OFFSET_REASON ) );
if( PN_NAME_OK != reason )
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() Name removing failed: 0x%x"), reason ) );
ASSERT(0);
if( iClientShutdownStatus )
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() completing shutdown") ) );
User::RequestComplete(iClientShutdownStatus, KErrGeneral );
iClientShutdownStatus = NULL;
}
}
else
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() Name removed succesfully") ) );
iName.Zero();
iMessageBufferPtr.SetLength( 0 );
iStatus = KRequestPending;
iIscApi.Receive( iStatus, iMessageBufferPtr, iReadLength );
SetActive();
}
break;
}
default:
{
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() unknown msg 0x%x"), msgId ) );
break;
}
}
C_TRACE( (_T("CBcaToIsc::HandleNameServiceMsg() <-") ) );
}
/**
* Handles received messages from resource PN_PIPE
*/
void CBcaToIsc::HandlePipeMsg( const TIsiReceiveC& aIsiMsg )
{
C_TRACE( (_T("CBcaToIsc::HandlePipeMsg() ->") ) );
TInt msgId( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_MESSAGEID ) );
switch( msgId )
{
case PNS_PEP_CTRL_REQ:
{
C_TRACE( (_T("CBcaToIsc::HandlePipeMsg() PNS_PEP_CTRL_REQ") ) );
HandlePepCtrlReq( aIsiMsg );
break;
}
default:
{
C_TRACE( (_T("CBcaToIsc::HandlePipeMsg() unknown msg 0x%x"), msgId ) );
ASSERT(0);
break;
}
}
C_TRACE( (_T("CBcaToIsc::HandlePipeMsg() <-") ) );
}
/**
* Handles PNS_PEP_CTRL_REQ
*/
void CBcaToIsc::HandlePepCtrlReq( const TIsiReceiveC& aIsiMsg )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() ->") ) );
TUint8 pipeHandle( aIsiMsg.Get8bit(
ISI_HEADER_SIZE + PNS_PEP_CTRL_REQ_OFFSET_PIPEHANDLE ) );
TUint8 pepCtrlId( aIsiMsg.Get8bit(
ISI_HEADER_SIZE + PNS_PEP_CTRL_REQ_OFFSET_PEPCTRLID ) );
TUint8 pepType( aIsiMsg.Get8bit(
ISI_HEADER_SIZE + PNS_PEP_CTRL_REQ_OFFSET_PEPTYPE ) );
TUint8 result( PN_PIPE_ERR_NOT_SUPPORTED );
TUint8 trId( aIsiMsg.Get8bit(
ISI_HEADER_OFFSET_TRANSID ) );
// Get sender device
TUint8 senderDevice( aIsiMsg.Get8bit(
ISI_HEADER_OFFSET_SENDERDEVICE ) );
// Get sender object
TUint8 senderObject( aIsiMsg.Get8bit(
ISI_HEADER_OFFSET_SENDEROBJECT ) );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() pipe handle: 0x%x"), pipeHandle ) );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() pep ctrl id: 0x%x"), pepCtrlId ) );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() pep type: 0x%x"), pepType ) );
TBuf8<KDataLength> data( aIsiMsg.GetData(
ISI_HEADER_SIZE + PNS_PEP_CTRL_REQ_OFFSET_PEPCTRLDATA,
KDataLength ) );
TUint8 devId( data[KDevIdIndex] );
TUint8 objId( data[KObjIdIndex] );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() dev id: 0x%x"), devId ) );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() obj id: 0x%x"), objId ) );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() iChannelNumber: 0x%x"), iChannelNumber ) );
if( PN_PEP_TYPE_BCA == pepType &&
THIS_DEVICE == devId &&
iChannelNumber == objId )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() PNS_PEP_CTRL_REQ for this PEP") ) );
result = PN_PIPE_NO_ERROR;
TInt ret( KErrNone );
if( PEP_BCA_OK != data[KStatusIndex] )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() PNS_PEP_CTRL_REQ with error 0x%x"), data[KStatusIndex] ) );
ret = KErrGeneral;
}
if( PEP_CTRL_ID_LOAN == pepCtrlId )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() ctrl id PEP_CTRL_ID_LOAN") ) );
if( iClientOpenStatus )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() completing open") ) );
User::RequestComplete( iClientOpenStatus, ret );
iClientOpenStatus = NULL;
}
}
else if( PEP_CTRL_ID_RETURNLOAN == pepCtrlId )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() ctrl id PEP_CTRL_ID_RETURNLOAN") ) );
if( iClientShutdownStatus )
{
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() completing shutdown") ) );
User::RequestComplete(iClientShutdownStatus, ret);
iClientShutdownStatus = NULL;
}
}
}
SendPepCtrlResp(
trId,
senderDevice,
senderObject,
pipeHandle,
pepCtrlId,
pepType,
result );
C_TRACE( (_T("CBcaToIsc::HandlePepCtrlReq() <-") ) );
}