/*
* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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: Handles SendSS command
*
*/
#include <CPhoneGsmParserBase.h>
#include <CPhoneGsmParserResult.h>
#include <PhoneGsmParser.h>
#include <CPhoneGsmOptionContainerBase.h>
#include "MSatSystemState.h"
#include "MSatApi.h"
#include "MSatUtils.h"
#include "MSatUiSession.h"
#include "SatSOpcodes.h"
#include "MSatSUiClientHandler.h"
#include "CSendSsHandler.h"
#include "SatLog.h"
#include "csatsendssrequestcompletehandler.h"
#include "csatsendssadditionalinfohandler.h"
#include "csatsendsshandler.h"
// CustomAPI returns KCustomApiSsGsmActive=0x01
const TInt KSsGsmActiveSuccess = 0x01;
// CustomAPI returns KCustomApiSsGsmRegistered=0x02
const TInt KSsGsmRegistered = 0x02;
// CustomAPI returns KCustomApiSsGsmProvisioned=0x04
const TInt KSsGsmProvisioned = 0x04;
// CustomAPI returns KCustomApiSsGsmQuiescent=0x08
const TInt KSsGsmQuiescent = 0x08;
// CustomAPI returns SsServiceFailedResp=0xFFFF
const TInt KSsServiceFailed = 0xFFFF;
// Error code for NetworkFailure = 0xFFFE
const TInt KSsNetworkError = 0xFFFE;
//interval wait for ussd send
const TInt KCallbackInterval = 1000000;
// Interval wait for additional info
const TInt KSSRequestCallbackInterval = 5000000;
// Ss OperationCode value.
const TInt KSsOperationShowFDNLIst = 0x05;
const TInt KSsOperationPasswordRegistration = 0x06;
// Ss error
const TInt KSsSimAtkCcRejected = 0x0D;
const TInt KTwo = 2;
// ======== MEMBER FUNCTIONS ========
// -----------------------------------------------------------------------------
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CSendSSHandler* CSendSSHandler::NewL( MSatUtils* aUtils )
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::NewL calling" )
CSendSSHandler* self = new( ELeave ) CSendSSHandler;
CleanupStack::PushL( self );
self->BaseConstructL( aUtils );
self->ConstructL();
CleanupStack::Pop( self );
LOG( SIMPLE, "SENDSS: CSendSSHandler::NewL exiting" )
return self;
}
// -----------------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------------
//
CSendSSHandler::~CSendSSHandler()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::~CSendSSHandler calling" )
Cancel();
// Destroy all objects.
delete iAdditionalInfoHandler;
delete iRequestCompleteHandler;
delete iPhoneGsmHandlerBase;
delete iParser;
delete iResult;
delete iPhoneGsmOptionContainerBase;
if ( iTimer )
{
iTimer->Cancel();
delete iTimer;
iTimer = NULL;
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::~CSendSSHandler exiting" )
}
// -----------------------------------------------------------------------------
// Processes the SS Request Complete.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::DispatchSsRequestComplete( TInt aErrCode )
{
LOG2( SIMPLE, "SENDSS: CSendSSHandler::DispatchSsRequestComplete \
called aErrCode: %i", aErrCode )
if ( ( KSsGsmActiveSuccess == aErrCode ) ||
( KSsGsmRegistered == aErrCode ) ||
( KSsGsmProvisioned == aErrCode ) ||
( KSsGsmQuiescent == aErrCode ) )
{
iSsResult = KErrNone;
}
else
{
iSsResult = aErrCode;
}
// Store result for later use
iSsResult = aErrCode;
iRequestCompleteArrived = ETrue;
//is additional info received
if ( iAdditionalInfoArrived )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::DispatchSsRequestComplete \
iAdditionalInfoArrived true" )
HandleSendSsResult();
}
else //if not 5 second timer to get additional info
{
if ( !iTimer )
{
LOG( SIMPLE,
"CSendSSHandler::DispatchSsRequestComplete iTimer false" )
TRAPD( err, iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); );
LOG2( NORMAL, "SENDSS: CSendSSHandler::DispatchSsRequestComplete \
CPeriodic::NewL err: %d ", err )
if ( KErrNone == err )
{
iTimer->Start( KSSRequestCallbackInterval,
KCallbackInterval, TCallBack( SSRequestCallback, this ) );
}
}
}
LOG( SIMPLE, "CSendSSHandler::DispatchSsRequestComplete exit" )
}
// -----------------------------------------------------------------------------
// Processes the SS aditional info.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::DispatchSsAdditionalInfo(
const TDesC& aAdditionalInfo )
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::DispatchSsAdditionalInfo called" )
iAdditionalInfoArrived = ETrue;
iAdditionalInfo.Copy( aAdditionalInfo );
LOG2( SIMPLE, "SENDSS: CSendSSHandler::DispatchSsAdditionalInfo length of\
aAdditionalInfo: %i", aAdditionalInfo.Length())
if ( aAdditionalInfo.Length() > 0 )
{
// This is special case due tsy will not send request complete.
if ( ( ( KSsOperationPasswordRegistration == aAdditionalInfo[0] ) ||
( KSsOperationShowFDNLIst == aAdditionalInfo[0] ) ) &&
( !iRequestCompleteArrived ) )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::DispatchSsAdditionalInfo special case" )
iSsResult = KErrNone;
iRequestCompleteArrived = ETrue;
}
}
//is requestcompletenotification reveived
if ( iRequestCompleteArrived )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::DispatchSsAdditionalInfo \
iRequestCompleteArrived true" )
HandleSendSsResult();
}
else //if not 5 second timer to get requestcompletenote
{
if ( !iTimer )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::DispatchSsAdditionalInfo iTimer false" )
TRAPD( err, iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); );
LOG2( NORMAL, "SENDSS: CSendSSHandler::DispatchSsAdditionalInfo \
CPeriodic::NewL err: %d ", err )
if ( KErrNone == err )
{
iTimer->Start( KSSRequestCallbackInterval,
KCallbackInterval, TCallBack( SSRequestCallback, this ) );
}
}
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::DispatchSsAdditionalInfo exit" )
}
// -----------------------------------------------------------------------------
// From class MSatCommand.
// Response from the client.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::ClientResponse()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::ClientResponse calling" )
if ( iQueryRsp.iAccepted && !iNotificationSent )
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::ClientResponse Sending notification" )
iNotificationSent = ETrue;
// Register service request
TRAP_IGNORE( iUtils->RegisterServiceRequestL(
ESatSProactiveNotification,
ESatSProactiveNotificationResponse,
this ) )
// Send notification
iUtils->SatUiHandler().UiSession()->SendCommand(
&iNotificationDataPckg,
&iNotificationRspPckg,
ESatSProactiveNotification );
}
else if ( iNotificationRsp.iAccepted && iNotificationSent )
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::ClientResponse Notification response" )
}
else // User reject
{
iUserAccepted = EFalse;
// Cannot return KPCmdNotAcceptedByUser (ETSI 11.14 v8.3.0 p65)
iSendSsRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KMeProblem;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KScreenBusy;
if ( iQueryRsp.iSessionTerminatedByUser )
{
LOG( NORMAL, "SENDSS: CSendSSHandler::ClientResponse \
ESessionTerminatedByUser" )
// Notify sim session end command that next sim session end
// should close the ui session.
iUtils->NotifyEvent( MSatUtils::ESessionTerminatedByUser );
}
SendTerminalResponse();
}
// Release Wait
if ( iSendWait.IsStarted() )
{
LOG( NORMAL, "SENDSS: CSendSSHandler::ClientResponse stop iSendWait" )
iSendWait.AsyncStop();
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::ClientResponse exiting" )
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Waits for indication of user rejection
// -----------------------------------------------------------------------------
//
void CSendSSHandler::Event( TInt aEvent )
{
LOG2( SIMPLE, "SENDSS: CSendSSHandler::Event calling, aEvent:%d", aEvent )
switch ( aEvent )
{
case MSatUtils::ECancelledUsingEndKey:
{
// Notify sim session end command that next sim session end
// should close the ui session.
iUtils->NotifyEvent( MSatUtils::ESessionTerminatedByUser );
// This event is handled as above, but notification must be done.
}
//lint -fallthrough intended here
case MSatUtils::ECommandCancelled:
{
// Check is there a confirmation on screen
if ( !iQueryOn || iNotificationSent )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::Event iNotificationSent true" )
// Cancel notification requests
iRequestCompleteHandler->Cancel();
iAdditionalInfoHandler->Cancel();
iSendSsRsp.iGeneralResult = RSat::KUssdTransactionTerminatedByUser;
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
SendTerminalResponse();
}
break;
}
default:
{
// Move event to base class
CSatCommandHandler::Event( aEvent );
}
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::Event exiting" )
}
// -----------------------------------------------------------------------------
// From class CActive.
// Cancels the sat request.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::DoCancel()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::DoCancel calling" )
iUtils->USatAPI().NotifySendSsCancel();
LOG( SIMPLE, "SENDSS: CSendSSHandler::DoCancel exiting" )
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Requests the command notification.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::IssueUSATRequest( TRequestStatus& aStatus )
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::IssueUSATRequest calling" )
// Clear the IPC package.
new (&iSendSsData) RSat::TSendSsV1();
iQueryOn = EFalse;
iQueryRsp.iAccepted = EFalse; // default
iNotificationRsp.iAccepted = EFalse;
iSendSsRsp.iGeneralResult = RSat::KPSessionTerminatedByUser; // default
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
iUtils->USatAPI().NotifySendSs( aStatus, iSendSsPckg );
// Unregister from events
iUtils->UnregisterEvent( this, MSatUtils::ECommandCancelled );
iUtils->UnregisterEvent( this, MSatUtils::ECancelledUsingEndKey );
LOG( SIMPLE, "SENDSS: CSendSSHandler::IssueUSATRequest exiting" )
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Precheck before executing the command.
// -----------------------------------------------------------------------------
//
TBool CSendSSHandler::CommandAllowed()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::CommandAllowed calling" )
// Allow this command to send terminal response
iTerminalRespSent = EFalse;
RMobilePhone::TMobilePhoneRegistrationStatus registrationStatus(
iUtils->SystemState().GetNetworkRegistrationStatus() );
TBool commandAllowed( ETrue );
// icon without alpha id
if ( ( RSat::EAlphaIdProvided != iSendSsData.iAlphaId.iStatus ) &&
( RSat::ESelfExplanatory == iSendSsData.iIconId.iQualifier ||
RSat::ENotSelfExplanatory == iSendSsData.iIconId.iQualifier ) )
{
iSendSsRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
commandAllowed = EFalse;
LOG( SIMPLE,
"SENDSS: CSendSSHandler::CommandAllowed icon without alpha id" )
}
else if ( ( RMobilePhone::ERegisteredOnHomeNetwork != registrationStatus ) &&
( RMobilePhone::ERegisteredRoaming != registrationStatus ) )
{
iSendSsRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KMeProblem;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KNoService;
commandAllowed = EFalse;
LOG( SIMPLE,
"SENDSS: CSendSSHandler::CommandAllowed no service" )
}
// Set icon command flag whether icon data was received and set qualifier
// to no icon id
// To be removed when icons are allowed in this command
else if ( ( RSat::ESelfExplanatory ==
iSendSsData.iIconId.iQualifier ) ||
( RSat::ENotSelfExplanatory ==
iSendSsData.iIconId.iQualifier ) )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::CommandAllowed ENoIconId" )
iIconCommand = ETrue;
iSendSsData.iIconId.iQualifier = RSat::ENoIconId;
}
else
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::CommandAllowed others" )
iIconCommand = EFalse;
}
if ( !commandAllowed )
{
SendTerminalResponse();
LOG( SIMPLE, "SENDSS: CSendSSHandler::CommandAllowed not allowed" )
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::CommandAllowed exiting" )
return commandAllowed;
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Answers for need of UI session.
// -----------------------------------------------------------------------------
//
TBool CSendSSHandler::NeedUiSession()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::NeedUiSession calling" )
iNeedUiSession = !TransparentSsSending();
// Notify Cover UI if it's supported
if ( iNeedUiSession && iUtils->CoverUiSupported() )
{
TSatCommandData medEventData;
medEventData.iPCmdNumber = RSat::ESendSs;
medEventData.iAlphaId = iSendSsData.iAlphaId;
if ( iUtils->SystemState().IsConfirmSatOperationsOn() )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::NeedUiSession KSatLongDuration" )
medEventData.iDuration.iNumOfUnits = KSatLongDuration;
}
else
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::NeedUiSession KSatDefaultDuration" )
medEventData.iDuration.iNumOfUnits = KSatDefaultDuration;
}
medEventData.iDuration.iTimeUnit = RSat::ESeconds;
medEventData.iIconID = iSendSsData.iIconId;
TSatCommandPckg tPckg( medEventData );
iUtils->RaiseSatEvent( tPckg );
}
LOG2( SIMPLE, "SENDSS: CSendSSHandler::NeedUiSession exiting,\
iNeedUiSession: %d", iNeedUiSession )
return iNeedUiSession;
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Called when USAT API notifies that command.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::HandleCommand()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::HandleCommand calling" )
iUtils->NotifyEvent( MSatUtils::ESendSsExecuting );
// This is true, by default
iUserAccepted = ETrue;
if ( iNeedUiSession )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleCommand iNeedUiSession true" )
TRAP_IGNORE(
// Register to listen user cancel events:
// Cancel key event from dialog
iUtils->RegisterL( this, MSatUtils::ECommandCancelled );
// End key from dialog
iUtils->RegisterL( this, MSatUtils::ECancelledUsingEndKey ) )
// Build Qyery and Notify packages
// Has to be casted to TInt before casting to TSatIconQualifier, because
// GCC warns about the direct cast.
const struct TSatIconId iconId = { iSendSsData.iIconId.iIdentifier,
static_cast<TSatIconQualifier>(
static_cast<TInt>( iSendSsData.iIconId.iQualifier ) ) };
if ( RSat::EAlphaIdNotPresent == iSendSsData.iAlphaId.iStatus )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleCommand EAlphaIdNotPresent" )
iQueryData.iAlphaIdStatus = ESatAlphaIdNotProvided;
iNotificationData.iAlphaIdStatus = ESatAlphaIdNotProvided;
}
else if ( RSat::EAlphaIdProvided == iSendSsData.iAlphaId.iStatus )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleCommand EAlphaIdProvided" )
iQueryData.iAlphaIdStatus = ESatAlphaIdNotNull;
iNotificationData.iAlphaIdStatus = ESatAlphaIdNotNull;
}
else
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleCommand ESatAlphaIdNull" )
iQueryData.iAlphaIdStatus = ESatAlphaIdNull;
iNotificationData.iAlphaIdStatus = ESatAlphaIdNull;
}
iQueryData.iCommand = ESatSSendSsQuery;
iQueryData.iQueryText = iSendSsData.iAlphaId.iAlphaId;
iQueryData.iIconId = iconId;
iNotificationSent = EFalse;
iNotificationData.iCommand = ESatSSendSsNotify;
iNotificationData.iText = iSendSsData.iAlphaId.iAlphaId;
iNotificationData.iIconId = iconId;
MSatUiSession* uiSession = iUtils->SatUiHandler().UiSession();
// Send either query or notification
if ( iQueryOn )
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::HandleCommand Sending Query" )
iNotificationSent = EFalse;
// Register service request
TRAP_IGNORE( iUtils->RegisterServiceRequestL(
ESatSProactiveQuery,
ESatSProactiveQueryResponse,
this ) )
// Send query
uiSession->SendCommand(
&iQueryPckg,
&iQueryRspPckg,
ESatSProactiveQuery );
}
else
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::HandleCommand Sending notification" )
iNotificationSent = ETrue;
// Register service request
TRAP_IGNORE( iUtils->RegisterServiceRequestL(
ESatSProactiveNotification,
ESatSProactiveNotificationResponse,
this ) )
// Send notification
uiSession->SendCommand(
&iNotificationDataPckg,
&iNotificationRspPckg,
ESatSProactiveNotification );
}
if ( !iSendWait.IsStarted() )
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::HandleCommand start iSendWait" )
// Start waiting response from the user
iSendWait.Start();
}
}
if ( iUserAccepted )
{
LOG( NORMAL,
"SENDSS: CSendSSHandler::HandleCommand iUserAccepted true" )
// Ready to send Ss string
TRAPD( err, SendSsStringL() )
if ( KErrNone != err )
{
LOG2( NORMAL, " Ss sending failed: %i", err )
iSendSsRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KMeProblem;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KNoSpecificMeProblem;
SendTerminalResponse();
}
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::HandleCommand exiting" )
}
// -----------------------------------------------------------------------------
// From class CSatCommandHandler.
// Indicates the failure of launching ui client
// -----------------------------------------------------------------------------
//
void CSendSSHandler::UiLaunchFailed()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::UiLaunchFailed calling" )
iSendSsRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KMeProblem;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KNoSpecificMeProblem;
SendTerminalResponse();
LOG( SIMPLE, "SENDSS: CSendSSHandler::UiLaunchFailed exiting" )
}
// -----------------------------------------------------------------------------
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
//lint -e{1403, 1769} Can not be initialized.
CSendSSHandler::CSendSSHandler() :
CSatCommandHandler(),
iSendSsData(),
iSendSsPckg( iSendSsData ),
iSendSsRsp(),
iSendSsRspPckg( iSendSsRsp ),
iQueryData(),
iQueryPckg( iQueryData ),
iQueryRsp(),
iQueryRspPckg( iQueryRsp ),
iNotificationData(),
iNotificationDataPckg( iNotificationData ),
iNotificationRsp(),
iNotificationRspPckg( iNotificationRsp ),
// To be removed when icons are allowed in this command
iIconCommand( EFalse )
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::CSendSSHandler calling - exiting" )
}
// -----------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::ConstructL()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::ConstructL calling" )
// Create additional info and request complete handlers
iAdditionalInfoHandler = CSatSendSsAdditionalInfoHandler::NewL(
*iUtils->CustomApi(), this );
iRequestCompleteHandler = CSatSendSsRequestCompleteHandler::NewL(
*iUtils->CustomApi(), this );
iPhoneGsmHandlerBase = new ( ELeave ) CSatSendSsHandler();
LOG( SIMPLE, "SENDSS: CSendSSHandler::ConstructL exiting" )
}
// -----------------------------------------------------------------------------
// Handles the Ss string sending.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::SendSsStringL()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::SendSsString calling" )
// Set default values
iSsResult = KErrArgument;
iRequestCompleteArrived = EFalse;
iAdditionalInfoArrived = EFalse;
//Parsing and interpreting
TBuf<RSat::KStringMaxSize> sendMessage;
sendMessage.Copy( iSendSsData.iSsString.iSsString );
// CPhoneGsmOptionContainerBase cannot be deleted before SendSsString
// complete, so the object is designed as a member in order that it can be
// deleted asychronously.
iParser = PhoneGsmParser::CreateParserL();
iResult = PhoneGsmParser::CreateResultL();
iPhoneGsmOptionContainerBase = PhoneGsmParser::CreateOptionContainerL();
//Update options
iPhoneGsmOptionContainerBase->SetOptionStatus( KPhoneOptionSend, ETrue );
//Parsing and interpreting
//Parse string
if ( iParser->ParseL( sendMessage, *iResult, *iPhoneGsmOptionContainerBase ) )
{
if ( PhoneGsmParser::DetermineContentType( *iResult ) ==
PhoneGsmParser::EContentSupplementaryService )
{
if ( !iRequestCompleteHandler->IsActive() )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendSsString start \
iRequestCompleteHandler" )
iRequestCompleteHandler->Start();
}
if ( !iAdditionalInfoHandler->IsActive() )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendSsString start \
iAdditionalInfoHandler" )
iAdditionalInfoHandler->Start();
}
// Make a Default Additional Info here, in case additional
// info field won't be received
// the field is a dummy
iAdditionalInfo.SetLength( 1 );
iAdditionalInfo[0] = 0x00;
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendSsString Processing Ss" )
// CPhoneGsmHandlerBase lives in all lifetime of
// CSendSSHandler. So, it designed as a member.
iPhoneGsmHandlerBase->ProcessL( *iResult );
}
else
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendSsString KCmdDataNotUnderstood" )
iSendSsRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
// Send terminal response
SendTerminalResponse();
}
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::SendSsString exiting" )
}
// -----------------------------------------------------------------------------
// Handles the result of Ss sending.
// -----------------------------------------------------------------------------
//
void CSendSSHandler::HandleSendSsResult()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::HandleSendSsResult calling" )
LOG2( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult iSsResult: %i", iSsResult )
// Remove progress bar from the screen
if ( KSsServiceFailed == iSsResult || KSsNetworkError == iSsResult )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult Clearing Progress bar.." )
iUtils->NotifyUiEvent( ESatSsEndEvent, ESatEventFailure, iSsResult );
// Send Error notification, but only if Alpha ID was provided
if ( ESatAlphaIdNotNull == iNotificationData.iAlphaIdStatus )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult Sending Ss note: \
Not Done" )
iUtils->NotifyUiEvent( ESatSsErrorEvent, ESatEventFailure,
iSsResult );
}
}
else if ( iNotificationSent )
{
// Remove the UI dialog
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult iNotificationSent true" )
iUtils->NotifyUiEvent( ESatSsEndEvent, ESatEventCompleteOk, iSsResult );
}
switch ( iSsResult )
{
case KErrGeneral: // Command not processed
{
iSendSsRsp.iGeneralResult = RSat::KMeUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KMeProblem;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KNoSpecificMeProblem;
break;
}
case KErrArgument:
{
iSendSsRsp.iGeneralResult = RSat::KCmdDataNotUnderstood;
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
break;
}
case KSsServiceFailed:
{
//This is a special case, TSY sends error value in additional info
//when SS is rejected by Call control
if ( KTwo <= iAdditionalInfo.Length() &&
KSsSimAtkCcRejected == iAdditionalInfo[1] )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult \
KInteractionWithCCPermanentError" )
iSendSsRsp.iGeneralResult =
RSat::KInteractionWithCCPermanentError;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
iSendSsRsp.iAdditionalInfo[0] = RSat::KActionNotAllowed;
}
else
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult KSsReturnError" )
iSendSsRsp.iGeneralResult = RSat::KSsReturnError;
iSendSsRsp.iAdditionalInfo.Copy( iAdditionalInfo );
}
iSendSsRsp.iInfoType = RSat::KMeProblem;
break;
}
case KSsNetworkError:
{
iSendSsRsp.iGeneralResult = RSat::KNetworkUnableToProcessCmd;
iSendSsRsp.iInfoType = RSat::KSatNetworkErrorInfo;
iSendSsRsp.iAdditionalInfo.SetLength( 1 );
if ( iAdditionalInfo.Length() > 1 )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult \
iAdditionalInfo.Length() > 1" )
iSendSsRsp.iAdditionalInfo[0] = \
( iAdditionalInfo[1] == RSat::KNoSpecificMeProblem ) \
? iAdditionalInfo[1] : ( iAdditionalInfo[1] | 0x80 );
}
else
{
iSendSsRsp.iAdditionalInfo[0] = RSat::KNoSpecificMeProblem;
}
break;
}
default:
{
// Convert terminal rsp if icon used
iSendSsRsp.iGeneralResult = RSat::KSuccess;
// If command had icon data and was done succesfully,
// report that icon was not shown.
// To be removed and correct handling (i.e. ClientResponse to
// notification is received) for general result
// KSuccessRequestedIconNotDisplayed must be added when icons are
// allowed in this command
if ( iIconCommand )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult iIconCommand \
true" )
iSendSsRsp.iGeneralResult =
RSat::KSuccessRequestedIconNotDisplayed;
}
if ( iAdditionalInfo.Length() )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::HandleSendSsResult \
iAdditionalInfo.Length >0" )
iSendSsRsp.iInfoType = RSat::KSendSsInfo;
iSendSsRsp.iAdditionalInfo.Copy( iAdditionalInfo );
}
else
{
iSendSsRsp.iInfoType = RSat::KNoAdditionalInfo;
iSendSsRsp.iAdditionalInfo.Zero();
}
break;
}
}
delete iResult;
iResult = NULL;
delete iParser;
iParser = NULL;
delete iPhoneGsmOptionContainerBase;
iPhoneGsmOptionContainerBase = NULL;
iRequestCompleteHandler->Cancel();
iAdditionalInfoHandler->Cancel();
// Send terminal response
SendTerminalResponse();
LOG( SIMPLE, "SENDSS: CSendSSHandler::HandleSendSsResult exiting" )
}
// -----------------------------------------------------------------------------
// SS sending should be transparent if alpha identifier is provided but it's
// length is 0. Also user query setting is not on.
// -----------------------------------------------------------------------------
//
TBool CSendSSHandler::TransparentSsSending()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::TransparentSsSending calling" )
TBool result( EFalse );
const RSat::TAlphaId alphaId( iSendSsData.iAlphaId );
// Store to member variable for later use
iQueryOn = iUtils->SystemState().IsConfirmSatOperationsOn();
if ( ( alphaId.iStatus == RSat::EAlphaIdProvided &&
alphaId.iAlphaId.Length() == 0 ) ||
alphaId.iStatus == RSat::EAlphaIdNull )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::TransparentSsSending EAlphaIdNull" )
if ( !iQueryOn )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::TransparentSsSending iQueryOn false" )
result = ETrue;
}
}
LOG2( SIMPLE, "SENDSS: CSendSSHandler::TransparentSsSending exiting: %i",
result )
return result;
}
// -----------------------------------------------------------------------------
// Sends terminal response, if not yet sent
// -----------------------------------------------------------------------------
//
void CSendSSHandler::SendTerminalResponse()
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::SendTerminalResponse calling" )
if ( !iTerminalRespSent )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendTerminalResponse iTerminalRespSent false" )
iTerminalRespSent = ETrue;
iSendSsRsp.SetPCmdNumber( iSendSsData.PCmdNumber() );
TerminalRsp( RSat::ESendSs, iSendSsRspPckg );
}
// Delete timer in case it is still active
if ( iTimer )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SendTerminalResponse iTimer true" )
iTimer->Cancel();
delete iTimer;
iTimer = NULL;
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::SendTerminalResponse exiting" )
}
// -----------------------------------------------------------------------------
// Callback for SendSS additionalinfo waiting timer.
// -----------------------------------------------------------------------------
//
TInt CSendSSHandler::SSRequestCallback( TAny* aPtr )
{
LOG( SIMPLE, "SENDSS: CSendSSHandler::SSRequestCallback calling" )
CSendSSHandler* handler =
static_cast<CSendSSHandler*>( aPtr );
if ( handler )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SSRequestCallback handler true" )
handler->HandleSendSsResult();
if ( handler->iTimer )
{
LOG( SIMPLE,
"SENDSS: CSendSSHandler::SSRequestCallback cancel iTimer" )
handler->iTimer->Cancel();
delete handler->iTimer;
handler->iTimer = NULL;
}
}
LOG( SIMPLE, "SENDSS: CSendSSHandler::SSRequestCallback exiting" )
return ( KErrNone );
}