/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the plugins of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "symbianengine.h" | |
#include "qnetworksession_impl.h" | |
#include <commdb.h> | |
#include <cdbcols.h> | |
#include <d32dbms.h> | |
#include <nifvar.h> | |
#include <QTimer> | |
#include <QTime> // For randgen seeding | |
#include <QtCore> // For randgen seeding | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
#include <QDebug> | |
#endif | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
#include <cmdestination.h> | |
#include <cmconnectionmethod.h> | |
#include <cmconnectionmethoddef.h> | |
#include <cmpluginwlandef.h> | |
#include <cmpluginpacketdatadef.h> | |
#include <cmplugindialcommondefs.h> | |
#else | |
#include <ApAccessPointItem.h> | |
#include <ApDataHandler.h> | |
#include <ApUtils.h> | |
#endif | |
#ifndef QT_NO_BEARERMANAGEMENT | |
QT_BEGIN_NAMESPACE | |
static const int KUserChoiceIAPId = 0; | |
SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate() | |
: numericId(0), connectionId(0) | |
{ | |
} | |
SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate() | |
{ | |
} | |
SymbianEngine::SymbianEngine(QObject *parent) | |
: QBearerEngine(parent), CActive(CActive::EPriorityHigh), iFirstUpdate(true), ipCommsDB(0), | |
iInitOk(true), iUpdatePending(false), ipAccessPointsAvailabilityScanner(0) | |
{ | |
} | |
void SymbianEngine::initialize() | |
{ | |
QMutexLocker locker(&mutex); | |
CActiveScheduler::Add(this); | |
// Seed the randomgenerator | |
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); | |
TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP)); | |
if (error != KErrNone) { | |
iInitOk = false; | |
return; | |
} | |
TRAP(error, StartConnectionMonitorNotifyL()); | |
if (error != KErrNone) { | |
iInitOk = false; | |
return; | |
} | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
TRAP(error, iCmManager.OpenL()); | |
if (error != KErrNone) { | |
iInitOk = false; | |
return; | |
} | |
#endif | |
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate; | |
cpPriv->name = "UserChoice"; | |
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; | |
cpPriv->state = QNetworkConfiguration::Discovered; | |
cpPriv->isValid = true; | |
cpPriv->id = QString::number(qHash(KUserChoiceIAPId)); | |
cpPriv->numericId = KUserChoiceIAPId; | |
cpPriv->connectionId = 0; | |
cpPriv->type = QNetworkConfiguration::UserChoice; | |
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; | |
cpPriv->roamingSupported = false; | |
QNetworkConfigurationPrivatePointer ptr(cpPriv); | |
userChoiceConfigurations.insert(ptr->id, ptr); | |
updateConfigurations(); | |
updateStatesToSnaps(); | |
updateAvailableAccessPoints(); // On first time updates (without WLAN scans) | |
// Start monitoring IAP and/or SNAP changes in Symbian CommsDB | |
startCommsDatabaseNotifications(); | |
} | |
void SymbianEngine::StartConnectionMonitorNotifyL() | |
{ | |
iConnectionMonitor.ConnectL(); | |
CleanupClosePushL(iConnectionMonitor); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
User::LeaveIfError(iConnectionMonitor.SetUintAttribute(EBearerIdAll, 0, KBearerGroupThreshold, 1)); | |
#endif | |
iConnectionMonitor.NotifyEventL(*this); | |
CleanupStack::Pop(); | |
} | |
SymbianEngine::~SymbianEngine() | |
{ | |
Cancel(); | |
//The scanner may be using the connection monitor so it needs to be | |
//deleted first while the handle is still valid. | |
delete ipAccessPointsAvailabilityScanner; | |
iConnectionMonitor.CancelNotifications(); | |
iConnectionMonitor.Close(); | |
// CCommsDatabase destructor and RCmManager.Close() use cleanup stack. Since QNetworkConfigurationManager | |
// is a global static, but the time we are here, E32Main() has been exited already and | |
// the thread's default cleanup stack has been deleted. Without this line, a | |
// 'E32USER-CBase 69' -panic will occur. | |
CTrapCleanup* cleanup = CTrapCleanup::New(); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
iCmManager.Close(); | |
#endif | |
delete ipCommsDB; | |
delete cleanup; | |
} | |
void SymbianEngine::delayedConfigurationUpdate() | |
{ | |
QMutexLocker locker(&mutex); | |
if (iUpdatePending) { | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug("QNCM delayed configuration update (ECommit or ERecover occurred)."); | |
#endif | |
TRAPD(error, updateConfigurationsL()); | |
if (error == KErrNone) { | |
updateStatesToSnaps(); | |
} | |
iUpdatePending = false; | |
// Start monitoring again. | |
if (!IsActive()) { | |
SetActive(); | |
// Start waiting for new notification | |
ipCommsDB->RequestNotification(iStatus); | |
} | |
} | |
} | |
bool SymbianEngine::hasIdentifier(const QString &id) | |
{ | |
QMutexLocker locker(&mutex); | |
return accessPointConfigurations.contains(id) || | |
snapConfigurations.contains(id) || | |
userChoiceConfigurations.contains(id); | |
} | |
QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const | |
{ | |
QNetworkConfigurationManager::Capabilities capFlags; | |
capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces | | |
QNetworkConfigurationManager::DirectConnectionRouting | | |
QNetworkConfigurationManager::SystemSessionSupport | | |
QNetworkConfigurationManager::DataStatistics | | |
QNetworkConfigurationManager::NetworkSessionRequired; | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming | | |
QNetworkConfigurationManager::ForcedRoaming; | |
#endif | |
return capFlags; | |
} | |
QNetworkSessionPrivate *SymbianEngine::createSessionBackend() | |
{ | |
return new QNetworkSessionPrivateImpl(this); | |
} | |
void SymbianEngine::requestUpdate() | |
{ | |
QMutexLocker locker(&mutex); | |
if (!iInitOk || iUpdateGoingOn) { | |
return; | |
} | |
iUpdateGoingOn = true; | |
stopCommsDatabaseNotifications(); | |
updateConfigurations(); // Synchronous call | |
updateAvailableAccessPoints(); // Asynchronous call | |
} | |
void SymbianEngine::updateConfigurations() | |
{ | |
if (!iInitOk) | |
return; | |
TRAP_IGNORE(updateConfigurationsL()); | |
} | |
void SymbianEngine::updateConfigurationsL() | |
{ | |
QList<QString> knownConfigs = accessPointConfigurations.keys(); | |
QList<QString> knownSnapConfigs = snapConfigurations.keys(); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
// S60 version is >= Series60 3rd Edition Feature Pack 2 | |
TInt error = KErrNone; | |
// Loop through all IAPs | |
RArray<TUint32> connectionMethods; // IAPs | |
CleanupClosePushL(connectionMethods); | |
iCmManager.ConnectionMethodL(connectionMethods); | |
for(int i = 0; i < connectionMethods.Count(); i++) { | |
RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]); | |
CleanupClosePushL(connectionMethod); | |
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)); | |
if (accessPointConfigurations.contains(ident)) { | |
knownConfigs.removeOne(ident); | |
} else { | |
SymbianNetworkConfigurationPrivate* cpPriv = NULL; | |
TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod)); | |
if (error == KErrNone) { | |
QNetworkConfigurationPrivatePointer ptr(cpPriv); | |
accessPointConfigurations.insert(ptr->id, ptr); | |
if (!iFirstUpdate) { | |
// Emit configuration added. Connected slots may throw execptions | |
// which propagate here --> must be converted to leaves (standard | |
// std::exception would cause any TRAP trapping this function to terminate | |
// program). | |
QT_TRYCATCH_LEAVING(updateActiveAccessPoints()); | |
updateStatesToSnaps(); | |
mutex.unlock(); | |
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr)); | |
mutex.lock(); | |
} | |
} | |
} | |
CleanupStack::PopAndDestroy(&connectionMethod); | |
} | |
CleanupStack::PopAndDestroy(&connectionMethods); | |
// Loop through all SNAPs | |
RArray<TUint32> destinations; | |
CleanupClosePushL(destinations); | |
iCmManager.AllDestinationsL(destinations); | |
for(int i = 0; i < destinations.Count(); i++) { | |
RCmDestination destination; | |
// Some destinatsions require ReadDeviceData -capability (MMS/WAP) | |
// The below function will leave in these cases. Don't. Proceed to | |
// next destination (if any). | |
TRAPD(error, destination = iCmManager.DestinationL(destinations[i])); | |
if (error == KErrPermissionDenied) { | |
continue; | |
} else { | |
User::LeaveIfError(error); | |
} | |
CleanupClosePushL(destination); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX + | |
QString::number(qHash(destination.Id())); | |
if (snapConfigurations.contains(ident)) { | |
knownSnapConfigs.removeOne(ident); | |
} else { | |
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate; | |
HBufC *pName = destination.NameLC(); | |
QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length())); | |
CleanupStack::PopAndDestroy(pName); | |
pName = NULL; | |
cpPriv->isValid = true; | |
cpPriv->id = ident; | |
cpPriv->numericId = destination.Id(); | |
cpPriv->connectionId = 0; | |
cpPriv->state = QNetworkConfiguration::Defined; | |
cpPriv->type = QNetworkConfiguration::ServiceNetwork; | |
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; | |
cpPriv->roamingSupported = false; | |
QNetworkConfigurationPrivatePointer ptr(cpPriv); | |
snapConfigurations.insert(ident, ptr); | |
if (!iFirstUpdate) { | |
QT_TRYCATCH_LEAVING(updateActiveAccessPoints()); | |
updateStatesToSnaps(); | |
mutex.unlock(); | |
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr)); | |
mutex.lock(); | |
} | |
} | |
// Loop through all connection methods in this SNAP | |
QMap<unsigned int, QNetworkConfigurationPrivatePointer> connections; | |
for (int j=0; j < destination.ConnectionMethodCount(); j++) { | |
RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j); | |
CleanupClosePushL(connectionMethod); | |
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId); | |
QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)); | |
// Check that IAP can be found from accessPointConfigurations list | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); | |
if (!ptr) { | |
SymbianNetworkConfigurationPrivate *cpPriv = NULL; | |
TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod)); | |
if (error == KErrNone) { | |
ptr = QNetworkConfigurationPrivatePointer(cpPriv); | |
accessPointConfigurations.insert(ptr->id, ptr); | |
if (!iFirstUpdate) { | |
QT_TRYCATCH_LEAVING(updateActiveAccessPoints()); | |
updateStatesToSnaps(); | |
mutex.unlock(); | |
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr)); | |
mutex.lock(); | |
} | |
} | |
} else { | |
knownConfigs.removeOne(iface); | |
} | |
if (ptr) { | |
unsigned int priority; | |
TRAPD(error, priority = destination.PriorityL(connectionMethod)); | |
if (!error) | |
connections.insert(priority, ptr); | |
} | |
CleanupStack::PopAndDestroy(&connectionMethod); | |
} | |
QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident); | |
QMutexLocker snapConfigLocker(&privSNAP->mutex); | |
if (privSNAP->serviceNetworkMembers != connections) { | |
privSNAP->serviceNetworkMembers = connections; | |
// Roaming is supported only if SNAP contains more than one IAP | |
privSNAP->roamingSupported = privSNAP->serviceNetworkMembers.count() > 1; | |
snapConfigLocker.unlock(); | |
updateStatesToSnaps(); | |
mutex.unlock(); | |
QT_TRYCATCH_LEAVING(emit configurationChanged(privSNAP)); | |
mutex.lock(); | |
} | |
CleanupStack::PopAndDestroy(&destination); | |
} | |
CleanupStack::PopAndDestroy(&destinations); | |
#else | |
// S60 version is < Series60 3rd Edition Feature Pack 2 | |
CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP)); | |
// Loop through all IAPs | |
TUint32 apId = 0; | |
TInt retVal = pDbTView->GotoFirstRecord(); | |
while (retVal == KErrNone) { | |
pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); | |
if (accessPointConfigurations.contains(ident)) { | |
knownConfigs.removeOne(ident); | |
} else { | |
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate; | |
if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) { | |
QNetworkConfigurationPrivatePointer ptr(cpPriv); | |
accessPointConfigurations.insert(ident, ptr); | |
if (!iFirstUpdate) { | |
QT_TRYCATCH_LEAVING(updateActiveAccessPoints()); | |
updateStatesToSnaps(); | |
mutex.unlock(); | |
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr)); | |
mutex.lock(); | |
} | |
} else { | |
delete cpPriv; | |
} | |
} | |
retVal = pDbTView->GotoNextRecord(); | |
} | |
CleanupStack::PopAndDestroy(pDbTView); | |
#endif | |
QT_TRYCATCH_LEAVING(updateActiveAccessPoints()); | |
foreach (const QString &oldIface, knownConfigs) { | |
//remove non existing IAP | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface); | |
mutex.unlock(); | |
emit configurationRemoved(ptr); | |
QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr)); | |
mutex.lock(); | |
// Remove non existing IAP from SNAPs | |
foreach (const QString &iface, snapConfigurations.keys()) { | |
QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface); | |
// => Check if one of the IAPs of the SNAP is active | |
QMutexLocker snapConfigLocker(&ptr2->mutex); | |
QMutableMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr2->serviceNetworkMembers); | |
while (i.hasNext()) { | |
i.next(); | |
if (toSymbianConfig(i.value())->numericIdentifier() == | |
toSymbianConfig(ptr)->numericIdentifier()) { | |
i.remove(); | |
break; | |
} | |
} | |
} | |
} | |
foreach (const QString &oldIface, knownSnapConfigs) { | |
//remove non existing SNAPs | |
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface); | |
mutex.unlock(); | |
emit configurationRemoved(ptr); | |
QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr)); | |
mutex.lock(); | |
} | |
// find default configuration. | |
stopCommsDatabaseNotifications(); | |
TRAP_IGNORE(defaultConfig = defaultConfigurationL()); | |
startCommsDatabaseNotifications(); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
updateStatesToSnaps(); | |
#endif | |
} | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL( | |
RCmConnectionMethod& connectionMethod) | |
{ | |
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate; | |
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)); | |
HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName); | |
CleanupStack::PushL(pName); | |
QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length())); | |
CleanupStack::PopAndDestroy(pName); | |
pName = NULL; | |
TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType); | |
switch (bearerId) { | |
case KCommDbBearerCSD: | |
cpPriv->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case KCommDbBearerWcdma: | |
cpPriv->bearerType = QNetworkConfiguration::BearerWCDMA; | |
break; | |
case KCommDbBearerLAN: | |
cpPriv->bearerType = QNetworkConfiguration::BearerEthernet; | |
break; | |
case KCommDbBearerVirtual: | |
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; | |
break; | |
case KCommDbBearerPAN: | |
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; | |
break; | |
case KCommDbBearerWLAN: | |
cpPriv->bearerType = QNetworkConfiguration::BearerWLAN; | |
break; | |
default: | |
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; | |
break; | |
} | |
TInt error = KErrNone; | |
TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType); | |
switch (bearerType) { | |
case KUidPacketDataBearerType: | |
// "Packet data" Bearer => Mapping is done using "Access point name" | |
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName)); | |
break; | |
case KUidWlanBearerType: | |
// "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID | |
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID)); | |
break; | |
} | |
if (!pName) { | |
// "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number" | |
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum)); | |
} | |
if (error == KErrNone && pName) { | |
CleanupStack::PushL(pName); | |
QT_TRYCATCH_LEAVING(cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length())); | |
CleanupStack::PopAndDestroy(pName); | |
pName = NULL; | |
} | |
cpPriv->state = QNetworkConfiguration::Defined; | |
TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected); | |
if (isConnected) { | |
cpPriv->state = QNetworkConfiguration::Active; | |
} | |
cpPriv->isValid = true; | |
cpPriv->id = ident; | |
cpPriv->numericId = iapId; | |
cpPriv->connectionId = 0; | |
cpPriv->type = QNetworkConfiguration::InternetAccessPoint; | |
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; | |
cpPriv->roamingSupported = false; | |
return cpPriv; | |
} | |
#else | |
bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb( | |
TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration) | |
{ | |
TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration)); | |
if (error != KErrNone) { | |
return false; | |
} | |
return true; | |
} | |
void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL( | |
TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration) | |
{ | |
CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB); | |
CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC(); | |
TBuf<KCommsDbSvrMaxColumnNameLength> name; | |
CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB); | |
TUint32 apId = pApUtils->WapIdFromIapIdL(aApId); | |
pDataHandler->AccessPointDataL(apId,*pAPItem); | |
pAPItem->ReadTextL(EApIapName, name); | |
if (name.Compare(_L("Easy WLAN")) == 0) { | |
// "Easy WLAN" won't be accepted to the Configurations list | |
User::Leave(KErrNotFound); | |
} | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(aApId)); | |
QT_TRYCATCH_LEAVING(apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length())); | |
apNetworkConfiguration->isValid = true; | |
apNetworkConfiguration->id = ident; | |
apNetworkConfiguration->numericId = aApId; | |
apNetworkConfiguration->connectionId = 0; | |
apNetworkConfiguration->state = (QNetworkConfiguration::Defined); | |
apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint; | |
apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose; | |
apNetworkConfiguration->roamingSupported = false; | |
switch (pAPItem->BearerTypeL()) { | |
case EApBearerTypeCSD: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EApBearerTypeGPRS: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EApBearerTypeHSCSD: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerHSPA; | |
break; | |
case EApBearerTypeCDMA: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerCDMA2000; | |
break; | |
case EApBearerTypeWLAN: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerWLAN; | |
break; | |
case EApBearerTypeLAN: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet; | |
break; | |
case EApBearerTypeLANModem: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet; | |
break; | |
default: | |
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerUnknown; | |
break; | |
} | |
CleanupStack::PopAndDestroy(pApUtils); | |
CleanupStack::PopAndDestroy(pAPItem); | |
CleanupStack::PopAndDestroy(pDataHandler); | |
} | |
#endif | |
QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration() | |
{ | |
QMutexLocker locker(&mutex); | |
return defaultConfig; | |
} | |
QStringList SymbianEngine::accessPointConfigurationIdentifiers() | |
{ | |
QMutexLocker locker(&mutex); | |
return accessPointConfigurations.keys(); | |
} | |
QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL() | |
{ | |
QNetworkConfigurationPrivatePointer ptr; | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
// Check Default Connection (SNAP or IAP) | |
TCmDefConnValue defaultConnectionValue; | |
iCmManager.ReadDefConnL(defaultConnectionValue); | |
if (defaultConnectionValue.iType == ECmDefConnDestination) { | |
QString iface = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX + | |
QString::number(qHash(defaultConnectionValue.iId)); | |
ptr = snapConfigurations.value(iface); | |
} else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) { | |
QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX + | |
QString::number(qHash(defaultConnectionValue.iId)); | |
ptr = accessPointConfigurations.value(iface); | |
} | |
#endif | |
if (ptr) { | |
QMutexLocker configLocker(&ptr->mutex); | |
if (ptr->isValid) | |
return ptr; | |
} | |
QString iface = QString::number(qHash(KUserChoiceIAPId)); | |
return userChoiceConfigurations.value(iface); | |
} | |
void SymbianEngine::updateActiveAccessPoints() | |
{ | |
bool online = false; | |
QList<QString> inactiveConfigs = accessPointConfigurations.keys(); | |
TRequestStatus status; | |
TUint connectionCount; | |
iConnectionMonitor.GetConnectionCount(connectionCount, status); | |
User::WaitForRequest(status); | |
// Go through all connections and set state of related IAPs to Active. | |
// Status needs to be checked carefully, because ConnMon lists also e.g. | |
// WLAN connections that are being currently tried --> we don't want to | |
// state these as active. | |
TUint connectionId; | |
TUint subConnectionCount; | |
TUint apId; | |
TInt connectionStatus; | |
if (status.Int() == KErrNone) { | |
for (TUint i = 1; i <= connectionCount; i++) { | |
iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount); | |
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); | |
User::WaitForRequest(status); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
if (!ptr) { | |
// If IAP was not found, check if the update was about EasyWLAN | |
ptr = configurationFromEasyWlan(apId, connectionId); | |
// Change the ident correspondingly | |
if (ptr) { | |
ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX + | |
QString::number(qHash(toSymbianConfig(ptr)->numericIdentifier())); | |
} | |
} | |
#endif | |
if (ptr) { | |
iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status); | |
User::WaitForRequest(status); | |
if (connectionStatus == KLinkLayerOpen) { | |
online = true; | |
inactiveConfigs.removeOne(ident); | |
ptr->mutex.lock(); | |
toSymbianConfig(ptr)->connectionId = connectionId; | |
ptr->mutex.unlock(); | |
// Configuration is Active | |
changeConfigurationStateTo(ptr, QNetworkConfiguration::Active); | |
} | |
} | |
} | |
} | |
// Make sure that state of rest of the IAPs won't be Active | |
foreach (const QString &iface, inactiveConfigs) { | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); | |
if (ptr) { | |
// Configuration is either Defined or Discovered | |
changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered); | |
} | |
} | |
if (iOnline != online) { | |
iOnline = online; | |
mutex.unlock(); | |
emit this->onlineStateChanged(online); | |
mutex.lock(); | |
} | |
} | |
void SymbianEngine::updateAvailableAccessPoints() | |
{ | |
if (!ipAccessPointsAvailabilityScanner) { | |
ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor); | |
} | |
if (ipAccessPointsAvailabilityScanner) { | |
// Scanning may take a while because WLAN scanning will be done (if device supports WLAN). | |
ipAccessPointsAvailabilityScanner->StartScanning(); | |
} | |
} | |
void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo) | |
{ | |
iUpdateGoingOn = false; | |
if (scanSuccessful) { | |
QList<QString> unavailableConfigs = accessPointConfigurations.keys(); | |
// Set state of returned IAPs to Discovered | |
// if state is not already Active | |
for(TUint i=0; i<iapInfo.iCount; i++) { | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX + | |
QString::number(qHash(iapInfo.iIap[i].iIapId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
if (ptr) { | |
unavailableConfigs.removeOne(ident); | |
QMutexLocker configLocker(&ptr->mutex); | |
if (ptr->state < QNetworkConfiguration::Active) { | |
// Configuration is either Discovered or Active | |
changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered); | |
} | |
} | |
} | |
// Make sure that state of rest of the IAPs won't be Active | |
foreach (const QString &iface, unavailableConfigs) { | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); | |
if (ptr) { | |
// Configuration is Defined | |
changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered); | |
} | |
} | |
} | |
updateStatesToSnaps(); | |
if (!iFirstUpdate) { | |
startCommsDatabaseNotifications(); | |
mutex.unlock(); | |
emit updateCompleted(); | |
mutex.lock(); | |
} else { | |
iFirstUpdate = false; | |
if (iScanInQueue) { | |
iScanInQueue = EFalse; | |
updateAvailableAccessPoints(); | |
} | |
} | |
} | |
void SymbianEngine::updateStatesToSnaps() | |
{ | |
// Go through SNAPs and set correct state to SNAPs | |
foreach (const QString &iface, snapConfigurations.keys()) { | |
bool discovered = false; | |
bool active = false; | |
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface); | |
QMutexLocker snapConfigLocker(&ptr->mutex); | |
// => Check if one of the IAPs of the SNAP is discovered or active | |
// => If one of IAPs is active, also SNAP is active | |
// => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered | |
QMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr->serviceNetworkMembers); | |
while (i.hasNext()) { | |
i.next(); | |
const QNetworkConfigurationPrivatePointer child = i.value(); | |
QMutexLocker configLocker(&child->mutex); | |
if ((child->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { | |
active = true; | |
break; | |
} else if ((child->state & QNetworkConfiguration::Discovered) == | |
QNetworkConfiguration::Discovered) { | |
discovered = true; | |
} | |
} | |
snapConfigLocker.unlock(); | |
if (active) { | |
changeConfigurationStateTo(ptr, QNetworkConfiguration::Active); | |
} else if (discovered) { | |
changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered); | |
} else { | |
changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined); | |
} | |
} | |
} | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
void SymbianEngine::updateMobileBearerToConfigs(TConnMonBearerInfo bearerInfo) | |
{ | |
QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i = | |
accessPointConfigurations.constBegin(); | |
while (i != accessPointConfigurations.constEnd()) { | |
QNetworkConfigurationPrivatePointer ptr = i.value(); | |
QMutexLocker locker(&ptr->mutex); | |
SymbianNetworkConfigurationPrivate *p = toSymbianConfig(ptr); | |
if (p->bearerType >= QNetworkConfiguration::Bearer2G && | |
p->bearerType <= QNetworkConfiguration::BearerHSPA) { | |
switch (bearerInfo) { | |
case EBearerInfoCSD: | |
p->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EBearerInfoWCDMA: | |
p->bearerType = QNetworkConfiguration::BearerWCDMA; | |
break; | |
case EBearerInfoCDMA2000: | |
p->bearerType = QNetworkConfiguration::BearerCDMA2000; | |
break; | |
case EBearerInfoGPRS: | |
p->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EBearerInfoHSCSD: | |
p->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EBearerInfoEdgeGPRS: | |
p->bearerType = QNetworkConfiguration::Bearer2G; | |
break; | |
case EBearerInfoWcdmaCSD: | |
p->bearerType = QNetworkConfiguration::BearerWCDMA; | |
break; | |
case EBearerInfoHSDPA: | |
p->bearerType = QNetworkConfiguration::BearerHSPA; | |
break; | |
case EBearerInfoHSUPA: | |
p->bearerType = QNetworkConfiguration::BearerHSPA; | |
break; | |
case EBearerInfoHSxPA: | |
p->bearerType = QNetworkConfiguration::BearerHSPA; | |
break; | |
} | |
} | |
++i; | |
} | |
} | |
#endif | |
bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr, | |
QNetworkConfiguration::StateFlags newState) | |
{ | |
ptr->mutex.lock(); | |
if (newState != ptr->state) { | |
ptr->state = newState; | |
ptr->mutex.unlock(); | |
mutex.unlock(); | |
emit configurationChanged(ptr); | |
mutex.lock(); | |
return true; | |
} else { | |
ptr->mutex.unlock(); | |
} | |
return false; | |
} | |
/* changeConfigurationStateAtMinTo function does not overwrite possible better | |
* state (e.g. Discovered state does not overwrite Active state) but | |
* makes sure that state is at minimum given state. | |
*/ | |
bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr, | |
QNetworkConfiguration::StateFlags newState) | |
{ | |
ptr->mutex.lock(); | |
if ((newState | ptr->state) != ptr->state) { | |
ptr->state = (ptr->state | newState); | |
ptr->mutex.unlock(); | |
mutex.unlock(); | |
emit configurationChanged(ptr); | |
mutex.lock(); | |
return true; | |
} else { | |
ptr->mutex.unlock(); | |
} | |
return false; | |
} | |
/* changeConfigurationStateAtMaxTo function overwrites possible better | |
* state (e.g. Discovered state overwrites Active state) and | |
* makes sure that state is at maximum given state (e.g. Discovered state | |
* does not overwrite Defined state). | |
*/ | |
bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr, | |
QNetworkConfiguration::StateFlags newState) | |
{ | |
ptr->mutex.lock(); | |
if ((newState & ptr->state) != ptr->state) { | |
ptr->state = (newState & ptr->state); | |
ptr->mutex.unlock(); | |
mutex.unlock(); | |
emit configurationChanged(ptr); | |
mutex.lock(); | |
return true; | |
} else { | |
ptr->mutex.unlock(); | |
} | |
return false; | |
} | |
void SymbianEngine::startCommsDatabaseNotifications() | |
{ | |
if (!iWaitingCommsDatabaseNotifications) { | |
iWaitingCommsDatabaseNotifications = ETrue; | |
if (!IsActive()) { | |
SetActive(); | |
// Start waiting for new notification | |
ipCommsDB->RequestNotification(iStatus); | |
} | |
} | |
} | |
void SymbianEngine::stopCommsDatabaseNotifications() | |
{ | |
if (iWaitingCommsDatabaseNotifications) { | |
iWaitingCommsDatabaseNotifications = EFalse; | |
Cancel(); | |
} | |
} | |
void SymbianEngine::RunL() | |
{ | |
QMutexLocker locker(&mutex); | |
if (iStatus != KErrCancel) { | |
// By default, start relistening notifications. Stop only if interesting event occurred. | |
iWaitingCommsDatabaseNotifications = true; | |
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int()); | |
switch (event) { | |
case RDbNotifier::ECommit: /** A transaction has been committed. */ | |
case RDbNotifier::ERecover: /** The database has been recovered */ | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int()); | |
#endif | |
// Mark that there is update pending. No need to ask more events, | |
// as we know we will be updating anyway when the timer expires. | |
if (!iUpdatePending) { | |
iUpdatePending = true; | |
iWaitingCommsDatabaseNotifications = false; | |
// Update after random time, so that many processes won't | |
// start updating simultaneously | |
updateConfigurationsAfterRandomTime(); | |
} | |
break; | |
default: | |
// Do nothing | |
break; | |
} | |
} | |
if (iWaitingCommsDatabaseNotifications) { | |
if (!IsActive()) { | |
SetActive(); | |
// Start waiting for new notification | |
ipCommsDB->RequestNotification(iStatus); | |
} | |
} | |
} | |
void SymbianEngine::DoCancel() | |
{ | |
QMutexLocker locker(&mutex); | |
ipCommsDB->CancelRequestNotification(); | |
} | |
void SymbianEngine::EventL(const CConnMonEventBase& aEvent) | |
{ | |
QMutexLocker locker(&mutex); | |
switch (aEvent.EventType()) { | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
case EConnMonBearerInfoChange: | |
{ | |
CConnMonBearerInfoChange* realEvent; | |
realEvent = (CConnMonBearerInfoChange*) &aEvent; | |
TUint connectionId = realEvent->ConnectionId(); | |
if (connectionId == EBearerIdAll) { | |
//Network level event | |
TConnMonBearerInfo bearerInfo = (TConnMonBearerInfo)realEvent->BearerInfo(); | |
updateMobileBearerToConfigs(bearerInfo); | |
} | |
break; | |
} | |
#endif | |
case EConnMonConnectionStatusChange: | |
{ | |
CConnMonConnectionStatusChange* realEvent; | |
realEvent = (CConnMonConnectionStatusChange*) &aEvent; | |
TInt connectionStatus = realEvent->ConnectionStatus(); | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId(); | |
#endif | |
if (connectionStatus == KConfigDaemonStartingRegistration) { | |
TUint connectionId = realEvent->ConnectionId(); | |
TUint subConnectionCount = 0; | |
TUint apId; | |
TRequestStatus status; | |
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); | |
User::WaitForRequest(status); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
if (!ptr) { | |
// Check if status was regarding EasyWLAN | |
ptr = configurationFromEasyWlan(apId, connectionId); | |
} | |
#endif | |
if (ptr) { | |
ptr->mutex.lock(); | |
toSymbianConfig(ptr)->connectionId = connectionId; | |
ptr->mutex.unlock(); | |
QT_TRYCATCH_LEAVING( | |
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(), | |
connectionId, QNetworkSession::Connecting) | |
); | |
} | |
} else if (connectionStatus == KLinkLayerOpen) { | |
// Connection has been successfully opened | |
TUint connectionId = realEvent->ConnectionId(); | |
TUint subConnectionCount = 0; | |
TUint apId; | |
TRequestStatus status; | |
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); | |
User::WaitForRequest(status); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
if (!ptr) { | |
// Check for EasyWLAN | |
ptr = configurationFromEasyWlan(apId, connectionId); | |
} | |
#endif | |
if (ptr) { | |
ptr->mutex.lock(); | |
toSymbianConfig(ptr)->connectionId = connectionId; | |
ptr->mutex.unlock(); | |
// Configuration is Active | |
QT_TRYCATCH_LEAVING( | |
if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) { | |
updateStatesToSnaps(); | |
} | |
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(), | |
connectionId, QNetworkSession::Connected); | |
if (!iOnline) { | |
iOnline = true; | |
emit this->onlineStateChanged(iOnline); | |
} | |
); | |
} | |
} else if (connectionStatus == KConfigDaemonStartingDeregistration) { | |
TUint connectionId = realEvent->ConnectionId(); | |
QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId); | |
if (ptr) { | |
QT_TRYCATCH_LEAVING( | |
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(), | |
connectionId, QNetworkSession::Closing) | |
); | |
} | |
} else if (connectionStatus == KLinkLayerClosed || | |
connectionStatus == KConnectionClosed) { | |
// Connection has been closed. Which of the above events is reported, depends on the Symbian | |
// platform. | |
TUint connectionId = realEvent->ConnectionId(); | |
QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId); | |
if (ptr) { | |
// Configuration is either Defined or Discovered | |
QT_TRYCATCH_LEAVING( | |
if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) { | |
updateStatesToSnaps(); | |
} | |
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(), | |
connectionId, QNetworkSession::Disconnected); | |
); | |
} | |
bool online = false; | |
foreach (const QString &iface, accessPointConfigurations.keys()) { | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); | |
QMutexLocker configLocker(&ptr->mutex); | |
if (ptr->state == QNetworkConfiguration::Active) { | |
online = true; | |
break; | |
} | |
} | |
if (iOnline != online) { | |
iOnline = online; | |
QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline)); | |
} | |
} | |
} | |
break; | |
case EConnMonIapAvailabilityChange: | |
{ | |
CConnMonIapAvailabilityChange* realEvent; | |
realEvent = (CConnMonIapAvailabilityChange*) &aEvent; | |
TConnMonIapInfo iaps = realEvent->IapAvailability(); | |
QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys(); | |
for ( TUint i = 0; i < iaps.Count(); i++ ) { | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX + | |
QString::number(qHash(iaps.iIap[i].iIapId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
if (ptr) { | |
// Configuration is either Discovered or Active | |
QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered)); | |
unDiscoveredConfigs.removeOne(ident); | |
} | |
} | |
foreach (const QString &iface, unDiscoveredConfigs) { | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); | |
if (ptr) { | |
// Configuration is Defined | |
QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined)); | |
} | |
} | |
// Something has in IAPs, update states to SNAPs | |
updateStatesToSnaps(); | |
} | |
break; | |
case EConnMonCreateConnection: | |
{ | |
// This event is caught to keep connection monitor IDs up-to-date. | |
CConnMonCreateConnection* realEvent; | |
realEvent = (CConnMonCreateConnection*) &aEvent; | |
TUint subConnectionCount = 0; | |
TUint apId; | |
TUint connectionId = realEvent->ConnectionId(); | |
TRequestStatus status; | |
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); | |
User::WaitForRequest(status); | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
if (!ptr) { | |
// If IAP was not found, check if the update was about EasyWLAN | |
ptr = configurationFromEasyWlan(apId, connectionId); | |
} | |
#endif | |
if (ptr) { | |
QMutexLocker configLocker(&ptr->mutex); | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name; | |
#endif | |
toSymbianConfig(ptr)->connectionId = connectionId; | |
} | |
} | |
break; | |
default: | |
// For unrecognized events | |
break; | |
} | |
} | |
/* | |
Returns the network configuration that matches the given SSID. | |
*/ | |
QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromSsid(const QString &ssid) | |
{ | |
QMutexLocker locker(&mutex); | |
// Browser through all items and check their name for match | |
QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i = | |
accessPointConfigurations.constBegin(); | |
while (i != accessPointConfigurations.constEnd()) { | |
QNetworkConfigurationPrivatePointer ptr = i.value(); | |
QMutexLocker configLocker(&ptr->mutex); | |
if (ptr->name == ssid) { | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug() << "QNCM EasyWlan uses real SSID: " << ssid; | |
#endif | |
return ptr; | |
} | |
++i; | |
} | |
return QNetworkConfigurationPrivatePointer(); | |
} | |
#ifdef SNAP_FUNCTIONALITY_AVAILABLE | |
// Tries to derive configuration from EasyWLAN. | |
// First checks if the interface brought up was EasyWLAN, then derives the real SSID, | |
// and looks up configuration based on that one. | |
QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId, | |
TUint connectionId) | |
{ | |
if (apId == iCmManager.EasyWlanIdL()) { | |
TRequestStatus status; | |
TBuf<50> easyWlanNetworkName; | |
iConnectionMonitor.GetStringAttribute( connectionId, 0, KNetworkName, | |
easyWlanNetworkName, status ); | |
User::WaitForRequest(status); | |
if (status.Int() == KErrNone) { | |
const QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(), | |
easyWlanNetworkName.Length()); | |
// Browser through all items and check their name for match | |
QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i = | |
accessPointConfigurations.constBegin(); | |
while (i != accessPointConfigurations.constEnd()) { | |
QNetworkConfigurationPrivatePointer ptr = i.value(); | |
QMutexLocker configLocker(&ptr->mutex); | |
if (ptr->name == realSSID) { | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug() << "QNCM EasyWlan uses real SSID: " << realSSID; | |
#endif | |
return ptr; | |
} | |
++i; | |
} | |
} | |
} | |
return QNetworkConfigurationPrivatePointer(); | |
} | |
#endif | |
// Sessions may use this function to report configuration state changes, | |
// because on some Symbian platforms (especially Symbian^3) all state changes are not | |
// reported by the RConnectionMonitor, in particular in relation to stop() call, | |
// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize | |
// this data here so that other sessions may benefit from it too (not all sessions necessarily have | |
// RConnection progress notifiers available but they relay on having e.g. disconnected information from | |
// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome. | |
void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState) | |
{ | |
QMutexLocker locker(&mutex); | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState; | |
#endif | |
switch (newState) { | |
case QNetworkSession::Disconnected: | |
{ | |
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX + | |
QString::number(qHash(accessPointId)); | |
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); | |
if (ptr) { | |
// Configuration is either Defined or Discovered | |
if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) { | |
updateStatesToSnaps(); | |
} | |
locker.unlock(); | |
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(), | |
toSymbianConfig(ptr)->connectionIdentifier(), | |
QNetworkSession::Disconnected); | |
locker.relock(); | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
// Waits for 2..6 seconds. | |
void SymbianEngine::updateConfigurationsAfterRandomTime() | |
{ | |
int iTimeToWait = qMax(1000, (qAbs(qrand()) % 68) * 100); | |
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG | |
qDebug("QNCM waiting random time: %d ms", iTimeToWait); | |
#endif | |
QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate())); | |
} | |
QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId) | |
{ | |
QNetworkConfiguration item; | |
QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i = | |
accessPointConfigurations.constBegin(); | |
while (i != accessPointConfigurations.constEnd()) { | |
QNetworkConfigurationPrivatePointer ptr = i.value(); | |
if (toSymbianConfig(ptr)->connectionIdentifier() == aConnectionId) | |
return ptr; | |
++i; | |
} | |
return QNetworkConfigurationPrivatePointer(); | |
} | |
AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner, | |
RConnectionMonitor& connectionMonitor) | |
: CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor) | |
{ | |
CActiveScheduler::Add(this); | |
} | |
AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner() | |
{ | |
Cancel(); | |
} | |
void AccessPointsAvailabilityScanner::DoCancel() | |
{ | |
iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute); | |
iScanActive = EFalse; | |
iOwner.iScanInQueue = EFalse; | |
} | |
void AccessPointsAvailabilityScanner::StartScanning() | |
{ | |
if (!iScanActive) { | |
iScanActive = ETrue; | |
if (iOwner.iFirstUpdate) { | |
// On first update (the mgr is being instantiated) update only those bearers who | |
// don't need time-consuming scans (WLAN). | |
// Note: EBearerIdWCDMA covers also GPRS bearer | |
iConnectionMonitor.GetPckgAttribute(EBearerIdWCDMA, 0, KIapAvailability, iIapBuf, iStatus); | |
} else { | |
iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus); | |
} | |
if (!IsActive()) { | |
SetActive(); | |
} | |
} else { | |
// Queue scan for getting WLAN info after first request returns | |
if (iOwner.iFirstUpdate) { | |
iOwner.iScanInQueue = ETrue; | |
} | |
} | |
} | |
void AccessPointsAvailabilityScanner::RunL() | |
{ | |
QMutexLocker locker(&iOwner.mutex); | |
iScanActive = EFalse; | |
if (iStatus.Int() != KErrNone) { | |
iIapBuf().iCount = 0; | |
QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf())); | |
} else { | |
QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf())); | |
} | |
} | |
QT_END_NAMESPACE | |
#endif // QT_NO_BEARERMANAGEMENT |