// Copyright (c) 2001-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:
// Implements the functionality required to provide clients with
// signal strength information.
//
//
/**
@file
*/
#include <testconfigfileparser.h>
#include "CSimSignalStrength.h"
#include "CSimPhone.h"
#include "Simlog.h"
#include "simtsyglobalproperties.h"
const TInt KSignalStrengthGranularity=5; // < Granularity for signal strength list array
CSimSignalStrength* CSimSignalStrength::NewL(CSimPhone* aPhone)
/**
* Standard two-phase constructor.
* @param aPhone The parent phone object.
* @return CSimSignalStrength The new signal strength class.
*/
{
CSimSignalStrength* self=new(ELeave) CSimSignalStrength(aPhone);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
CSimSignalStrength::CSimSignalStrength(CSimPhone* aPhone)
: iPhone(aPhone)
/**
* Trivial first phase construction.
* @param aPhone The parent phone object.
*/
{
}
void CSimSignalStrength::ConstructL()
/**
* Second phase construction. Create instances of the necessary heap-based
* objects and read in the signal strength information from the configuration file.
* Finally, if any signal strength tags have been read, the initial values
* will be loaded and the timer started.
*
* Entries in the configuration file will take the following format:
* "SignalStrengthLevel= <duration>, <dB Level>, <Bar Level>"
* A number of these entries may be included to create a signal strength profile
* for the duration of the test.
*/
{
iTimer=CSimTimer::NewL(iPhone);
iSignalStrengthInfo=new(ELeave) CArrayFixFlat<TSignalStrengthInfo>(KSignalStrengthGranularity);
LOGSS1("Starting to parse Signal Strength config parameters...");
const CTestConfigItem* item=NULL;
TInt ret=KErrNone;
item=CfgFile()->Item(KSSNotifyCap);
if (item != NULL)
{
TInt notifyCap;
ret = CTestConfig::GetElement(item->Value(),KStdDelimiter,0,notifyCap);
if(ret != KErrNone)
{
iNotifyCapability = 0;
}
else
{
iNotifyCapability = notifyCap;
}
}
else
{
iNotifyCapability = 0;
}
TInt count=CfgFile()->ItemCount(KSSLevel);
TInt i;
for(i=0;i<count;i++)
{
item=CfgFile()->Item(KSSLevel,i);
if(!item)
break;
TInt duration,ss,ssb,err;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,duration);
if(ret!=KErrNone)
{
LOGPARSERR("duration",ret,0,&KSSLevel);
continue;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,ss);
if(ret!=KErrNone)
{
LOGPARSERR("ss",ret,1,&KSSLevel);
continue;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,ssb);
if(ret!=KErrNone)
{
LOGPARSERR("ssb",ret,2,&KSSLevel);
continue;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,err);
if (ret == KErrNotFound)
{
err = KErrNone;
}
else
{
LOGPARSERRANGE("ssb",ret,3,&KSSLevel,"0 or -1");
}
TSignalStrengthInfo ssInfo;
ssInfo.iDuration=duration;
ssInfo.iLevel=ss;
ssInfo.iBar=(TInt8)ssb;
ssInfo.iErr = err;
iSignalStrengthInfo->AppendL(ssInfo);
}
LOGSS1("...Finished parsing Signal Strength config parameters...");
if(iSignalStrengthInfo->Count()!=0)
{
iSSIndex=0;
iCurrentLevel=iSignalStrengthInfo->At(0).iLevel;
iCurrentBar=iSignalStrengthInfo->At(0).iBar;
iCurrentError = iSignalStrengthInfo->At(0).iErr;
iTimer->Start(iSignalStrengthInfo->At(0).iDuration,this);
}
//still have to listen on deprecated P&S uids
iSignalStrengthChange = CSimPubSubChange::NewL(this, CSimPubSub::TPubSubProperty(KUidSimtsyCategoryLocal, KSimtsySignalStrengthChange, KSimtsySignalStrengthChangeType));
iPSSignalStrengthChange = CSimPubSubChange::NewL(this, CSimPubSub::TPubSubProperty(KUidPSSimTsyCategory, KPSSimTsySignalStrengthChange, KPSSimTsySignalStrengthChangeKeyType));
}
CSimSignalStrength::~CSimSignalStrength()
/**
* Standard destructor. Destroy the heap-based object owned by this object.
*/
{
delete iTimer;
delete iSignalStrengthInfo;
delete iSignalStrengthChange;
delete iPSSignalStrengthChange;
}
TInt CSimSignalStrength::GetSignalCaps(TTsyReqHandle aReqHandle,TDes8* aPckg1)
/**
* Retrieve signal strength capability information. This function completes the
* client's request synchronously. If the configuration file contains any signal
* strength profile information, then it indicates support for signal strength
* requests, otherwise it does not.
*
* @param aReqHandle The request handle associated with this request.
* @param aPckg1 The first parameter package. This will be populated with the
* capability data to be returned.
* @return TInt Standard error value.
*/
{
TPckg<TUint32>* signalCapsPckg=(TPckg<TUint32>*)aPckg1;
TUint32& signalCaps=(*signalCapsPckg)();
if (iNotifyCapability != 0)
{
signalCaps= RMobilePhone::KCapsGetSignalStrength |
RMobilePhone::KCapsNotifySignalStrengthChange;
}
else if(iSignalStrengthInfo->Count()==0)
{
signalCaps=0;
}
else if((iSignalStrengthInfo->Count()-1)<=iSSIndex)
{
signalCaps= RMobilePhone::KCapsGetSignalStrength;
}
else
{
signalCaps= RMobilePhone::KCapsGetSignalStrength |
RMobilePhone::KCapsNotifySignalStrengthChange;
}
iPhone->ReqCompleted(aReqHandle,KErrNone);
return KErrNone;
}
TInt CSimSignalStrength::GetSignalStrength(TTsyReqHandle aReqHandle,TDes8* aPckg1, TDes8* aPckg2)
/**
* Return the current signal strength information. This function completes synchronously.
* If the configuration file contains any signal strength profile information, the
* request completes successfully, otherwise it completes with KErrNotSupported.
*
* @param aReqHandle The request handle associated with this request.
* @param aPckg1 The first parameter package. This is populated with the signal
* strength dB level.
* @param aPckg2 The second parameter package. This is populated with the signal
* strength bar level.
* @return TInt Standard error value.
*/
{
LOGSS1(">>CSimSignalStrength::GetSignalStrength");
TPckg<TInt32>* ssPckg=(TPckg<TInt32>*)aPckg1;
TInt32& ss=(*ssPckg)();
TPckg<TInt8>* ssbPckg=(TPckg<TInt8>*)aPckg2;
TInt8& ssb=(*ssbPckg)();
if(iSignalStrengthInfo->Count()==0 && iNotifyCapability == 0)
{
iPhone->ReqCompleted(aReqHandle,KErrNotSupported);
return KErrNone;
}
ss=iCurrentLevel;
ssb=iCurrentBar;
LOGSS3("<<CSimSignalStrength::GetSignalStrength with level=%d dB and bar=%d",iCurrentLevel,iCurrentBar);
iPhone->ReqCompleted(aReqHandle,iCurrentError);
return KErrNone;
}
TInt CSimSignalStrength::NotifySignalStrengthChange(TTsyReqHandle aReqHandle,TDes8* aPckg1, TDes8* aPckg2)
/**
* Register a client's interest in being notified when the signal strength changes.
* This function records the request's parameters and awaits a change in signal
* strength before completing.
*
* @param aPckg1 The first parameter package. This is populated with the signal
* strength dB level.
* @param aPckg2 The second parameter package. This is populated with the signal
* strength bar level.
* @return TInt Standard error value.
*/
{
LOGSS1(">>CSimSignalStrength::NotifySignalStrengthChange");
TPckg<TInt32>* ssPckg=(TPckg<TInt32>*)aPckg1;
TInt32& ss=(*ssPckg)();
TPckg<TInt8>* ssbPckg=(TPckg<TInt8>*)aPckg2;
TInt8& ssb=(*ssbPckg)();
if(iSignalStrengthInfo->Count()==0 && iNotifyCapability == 0)
{
iPhone->ReqCompleted(aReqHandle,KErrNotSupported);
return KErrNone;
}
__ASSERT_ALWAYS(!iSSChangeNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding));
iSSChangeNotificationPending=ETrue;
iSSChangeNotificationReqHandle=aReqHandle;
iSSChangeNotificationSSLevel=&ss;
iSSChangeNotificationSSBarLevel=&ssb;
return KErrNone;
}
void CSimSignalStrength::NotifySignalStrengthChangeCancel()
/**
* Cancel a previous request to be notified of a change in signal strength.
*/
{
if(iSSChangeNotificationPending)
{
LOGSS1("CSimSignalStrength::NotifySignalStrengthChange has been cancelled");
iSSChangeNotificationPending=EFalse;
iPhone->ReqCompleted(iSSChangeNotificationReqHandle,KErrCancel);
}
else
LOGSS1("CSimSignalStrength::NotifySignalStrengthChange was not outstanding and hasn't been cancelled");
}
void CSimSignalStrength::TimerCallBack(TInt /*aId*/)
/**
* The timer callback function. This function will be called when the timer
* completes. It indicates a change in signal strength settings. So, the new
* signal strength settings must be loaded into the member variables representing
* the current settings and any pending signal strength notification requests must
* be completed. Finally, the next timer is started.
*
* @param aId This parameter is unused. It is only required for CSimXxx classes
* that have more than one timer instance and need to identify which
* timer has expired.
*/
{
iSSIndex++;
if(iSignalStrengthInfo->Count()<=iSSIndex)
return;
iCurrentLevel=iSignalStrengthInfo->At(iSSIndex).iLevel;
iCurrentBar=iSignalStrengthInfo->At(iSSIndex).iBar;
iCurrentError = iSignalStrengthInfo->At(iSSIndex).iErr;
if(iSSChangeNotificationPending)
{
iSSChangeNotificationPending=EFalse;
*iSSChangeNotificationSSLevel=iCurrentLevel;
*iSSChangeNotificationSSBarLevel=iCurrentBar;
LOGSS3("<<CSimSignalStrength::NotifySignalStrengthChange with level=%d dB and bar=%d",iCurrentLevel,iCurrentBar);
iPhone->ReqCompleted(iSSChangeNotificationReqHandle,iCurrentError);
}
iTimer->Start(iSignalStrengthInfo->At(iSSIndex).iDuration,this);
}
const CTestConfigSection* CSimSignalStrength::CfgFile()
/**
* Returns a pointer to the current configuration file section.
*
* @return CTestConfigSection A pointer to the current configuration file section.
*/
{
return iPhone->CfgFile();
}
/**
* Called by CSimSignalStrengthChange when a signal strength request has been received.
*
* @param aNewVal The new signal strength value (number of bars)
*/
void CSimSignalStrength::PubSubCallback(TInt aNewVal)
{
LOGSS2("CSimSignalStrength::SignalStrengthChangeCallBack newVal=%d", aNewVal);
if (iCurrentBar == aNewVal)
{
return;
}
iCurrentBar = (TInt8) aNewVal;
if(iSSChangeNotificationPending)
{
iSSChangeNotificationPending=EFalse;
*iSSChangeNotificationSSLevel=iCurrentLevel;
*iSSChangeNotificationSSBarLevel=iCurrentBar;
LOGSS3("<<CSimSignalStrength::NotifySignalStrengthChange with level=%d dB and bar=%d",iCurrentLevel,iCurrentBar);
iPhone->ReqCompleted(iSSChangeNotificationReqHandle,iCurrentError);
}
}