| /**************************************************************************** |
| ** |
| ** 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 |