qtmobility/src/bearer/qnetworkconfigmanager_maemo.cpp
branchRCL_3
changeset 9 5d007b20cfd0
parent 8 885c2596c964
child 10 cd2778e5acfe
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <string.h>
       
    43 
       
    44 #include "qnetworkconfigmanager_maemo_p.h"
       
    45 
       
    46 #include <QDebug>
       
    47 #include <QHash>
       
    48 
       
    49 #include <wlancond.h>
       
    50 #include <libicd-network-wlan-dev.h>
       
    51 #include <maemo_icd.h>
       
    52 #include <iapconf.h>
       
    53 #include <iapmonitor.h>
       
    54 
       
    55 QTM_BEGIN_NAMESPACE
       
    56 
       
    57 /* The IapAddTimer is a helper class that makes sure we update
       
    58  * the configuration only after all db additions to certain
       
    59  * iap are finished (after a certain timeout)
       
    60  */
       
    61 class _IapAddTimer : public QObject
       
    62 {
       
    63     Q_OBJECT
       
    64 
       
    65 public:
       
    66     _IapAddTimer() {}
       
    67     ~_IapAddTimer()
       
    68     {
       
    69 	if (timer.isActive()) {
       
    70 	    QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
       
    71 	    timer.stop();
       
    72 	}
       
    73     }
       
    74 
       
    75     void add(QString& iap_id, QNetworkConfigurationManagerPrivate *d);
       
    76 
       
    77     QString iap_id;
       
    78     QTimer timer;
       
    79     QNetworkConfigurationManagerPrivate *d;
       
    80 
       
    81 public Q_SLOTS:
       
    82     void timeout();
       
    83 };
       
    84 
       
    85 
       
    86 void _IapAddTimer::add(QString& id, QNetworkConfigurationManagerPrivate *d_ptr)
       
    87 {
       
    88     iap_id = id;
       
    89     d = d_ptr;
       
    90 
       
    91     if (timer.isActive()) {
       
    92 	QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
       
    93 	timer.stop();
       
    94     }
       
    95     timer.setSingleShot(true);
       
    96     QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
       
    97     timer.start(1500);
       
    98 }
       
    99 
       
   100 
       
   101 void _IapAddTimer::timeout()
       
   102 {
       
   103     d->addConfiguration(iap_id);
       
   104 }
       
   105 
       
   106 
       
   107 class IapAddTimer {
       
   108     QHash<QString, _IapAddTimer* > timers;
       
   109 
       
   110 public:
       
   111     IapAddTimer() {}
       
   112     ~IapAddTimer() {}
       
   113 
       
   114     void add(QString& iap_id, QNetworkConfigurationManagerPrivate *d);
       
   115     void del(QString& iap_id);
       
   116     void removeAll();
       
   117 };
       
   118 
       
   119 
       
   120 void IapAddTimer::removeAll()
       
   121 {
       
   122     QHashIterator<QString, _IapAddTimer* > i(timers);
       
   123     while (i.hasNext()) {
       
   124 	i.next();
       
   125 	_IapAddTimer *t = i.value();
       
   126 	delete t;
       
   127     }
       
   128     timers.clear();
       
   129 }
       
   130 
       
   131 
       
   132 void IapAddTimer::add(QString& iap_id, QNetworkConfigurationManagerPrivate *d)
       
   133 {
       
   134     if (timers.contains(iap_id)) {
       
   135 	_IapAddTimer *iap = timers.value(iap_id);
       
   136 	iap->add(iap_id, d);
       
   137     } else {
       
   138 	_IapAddTimer *iap = new _IapAddTimer;
       
   139 	iap->add(iap_id, d);
       
   140 	timers.insert(iap_id, iap);
       
   141     }
       
   142 }
       
   143 
       
   144 void IapAddTimer::del(QString& iap_id)
       
   145 {
       
   146     if (timers.contains(iap_id)) {
       
   147 	_IapAddTimer *iap = timers.take(iap_id);
       
   148 	delete iap;
       
   149     }
       
   150 }
       
   151 
       
   152 
       
   153 class IapMonitor : public Maemo::IAPMonitor
       
   154 {
       
   155 public:
       
   156     IapMonitor() : first_call(true) { }
       
   157 
       
   158     void setup(QNetworkConfigurationManagerPrivate *d);
       
   159     void cleanup();
       
   160 
       
   161 protected:
       
   162     void iapAdded(const QString &iapId);
       
   163     void iapRemoved(const QString &iapId);
       
   164 
       
   165 private:
       
   166     bool first_call;
       
   167 
       
   168     QNetworkConfigurationManagerPrivate *d;
       
   169     IapAddTimer timers;
       
   170 };
       
   171 
       
   172 Q_GLOBAL_STATIC(IapMonitor, iapMonitor);
       
   173 
       
   174 
       
   175 void IapMonitor::setup(QNetworkConfigurationManagerPrivate *d_ptr)
       
   176 {
       
   177     if (first_call) {
       
   178 	d = d_ptr;
       
   179 	first_call = false;
       
   180     }
       
   181 }
       
   182 
       
   183 
       
   184 void IapMonitor::cleanup()
       
   185 {
       
   186     if (!first_call) {
       
   187 	timers.removeAll();
       
   188 	first_call = true;
       
   189     }
       
   190 }
       
   191 
       
   192 
       
   193 void IapMonitor::iapAdded(const QString &iap_id)
       
   194 {
       
   195     /* We cannot know when the IAP is fully added to db, so a timer is
       
   196      * installed instead. When the timer expires we hope that IAP is added ok.
       
   197      */
       
   198     QString id = iap_id;
       
   199     timers.add(id, d);
       
   200 }
       
   201 
       
   202 
       
   203 void IapMonitor::iapRemoved(const QString &iap_id)
       
   204 {
       
   205     QString id = iap_id;
       
   206     d->deleteConfiguration(id);
       
   207 }
       
   208 
       
   209 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
       
   210 {
       
   211     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
       
   212     capFlags |= QNetworkConfigurationManager::DataStatistics;
       
   213     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
       
   214     capFlags |= QNetworkConfigurationManager::NetworkSessionRequired;
       
   215 }
       
   216 
       
   217 void QNetworkConfigurationManagerPrivate::init()
       
   218 {
       
   219     // Setup DBus Interface for ICD
       
   220     m_dbusInterface = new QDBusInterface(ICD_DBUS_API_INTERFACE,
       
   221                                          ICD_DBUS_API_PATH,
       
   222                                          ICD_DBUS_API_INTERFACE,
       
   223                                          QDBusConnection::systemBus(),
       
   224                                          this);
       
   225     connect(&m_scanTimer, SIGNAL(timeout()), this, SLOT(finishAsyncConfigurationUpdate()));
       
   226     m_scanTimer.setSingleShot(true);
       
   227 
       
   228     /* Turn on IAP state monitoring */
       
   229     startListeningStateSignalsForAllConnections();
       
   230 
       
   231     /* Turn on IAP add/remove monitoring */
       
   232     iapMonitor()->setup(this);
       
   233 
       
   234     /* We create a default configuration which is a pseudo config */
       
   235     QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   236     cpPriv->name = "UserChoice";
       
   237     cpPriv->state = QNetworkConfiguration::Discovered;
       
   238     cpPriv->isValid = true;
       
   239     cpPriv->id = OSSO_IAP_ANY;
       
   240     cpPriv->type = QNetworkConfiguration::UserChoice;
       
   241     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
       
   242     cpPriv->roamingSupported = false;
       
   243     cpPriv->manager = this;
       
   244     QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   245     userChoiceConfigurations.insert(cpPriv->id, ptr);
       
   246 }
       
   247 
       
   248 static inline QString network_attrs_to_security(uint network_attrs)
       
   249 {
       
   250     uint cap = 0;
       
   251     nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
       
   252     if (cap & WLANCOND_OPEN)
       
   253 	return "NONE";
       
   254     else if (cap & WLANCOND_WEP)
       
   255 	return "WEP";
       
   256     else if (cap & WLANCOND_WPA_PSK)
       
   257 	return "WPA_PSK";
       
   258     else if (cap & WLANCOND_WPA_EAP)
       
   259 	return "WPA_EAP";
       
   260     return "";
       
   261 }
       
   262 
       
   263 
       
   264 struct SSIDInfo {
       
   265     QString iap_id;
       
   266     QString wlan_security;
       
   267 };
       
   268 
       
   269 
       
   270 void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivate *ptr)
       
   271 {
       
   272     QNetworkConfiguration item;
       
   273     item.d = ptr;
       
   274     emit configurationChanged(item);
       
   275 }
       
   276 
       
   277 void QNetworkConfigurationManagerPrivate::deleteConfiguration(QString& iap_id)
       
   278 {
       
   279     /* Called when IAPs are deleted in db, in this case we do not scan
       
   280      * or read all the IAPs from db because it might take too much power
       
   281      * (multiple applications would need to scan and read all IAPs from db)
       
   282      */
       
   283     if (accessPointConfigurations.contains(iap_id)) {
       
   284 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iap_id);
       
   285 	if (priv.data()) {
       
   286 	    priv->isValid = false;
       
   287 #ifdef BEARER_MANAGEMENT_DEBUG
       
   288 	    qDebug() << "IAP" << iap_id << "was removed from storage.";
       
   289 #endif
       
   290 
       
   291 	    QNetworkConfiguration item;
       
   292 	    item.d = priv;
       
   293 	    emit configurationRemoved(item);
       
   294 	} else
       
   295 	    qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
       
   296     } else {
       
   297 #ifdef BEARER_MANAGEMENT_DEBUG
       
   298 	qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
       
   299 #endif
       
   300     }
       
   301 }
       
   302 
       
   303 
       
   304 uint32_t QNetworkConfigurationManagerPrivate::getNetworkAttrs(bool is_iap_id,
       
   305                                                               const QString& iap_id,
       
   306                                                               const QString& iap_type,
       
   307                                                               QString security_method)
       
   308 {
       
   309     guint network_attr = 0;
       
   310     dbus_uint32_t cap = 0;
       
   311 
       
   312     if (iap_type == "WLAN_INFRA")
       
   313 	cap |= WLANCOND_INFRA;
       
   314     else if (iap_type == "WLAN_ADHOC")
       
   315 	cap |= WLANCOND_ADHOC;
       
   316 
       
   317     if (security_method.isEmpty() && (cap & (WLANCOND_INFRA | WLANCOND_ADHOC))) {
       
   318 	Maemo::IAPConf saved_ap(iap_id);
       
   319 	security_method = saved_ap.value("wlan_security").toString();
       
   320     }
       
   321 
       
   322     if (!security_method.isEmpty()) {
       
   323 	if (security_method == "WEP")
       
   324 	    cap |= WLANCOND_WEP;
       
   325 	else if (security_method == "WPA_PSK")
       
   326 	    cap |= WLANCOND_WPA_PSK;
       
   327 	else if (security_method == "WPA_EAP")
       
   328 	    cap |= WLANCOND_WPA_EAP;
       
   329 	else if (security_method == "NONE")
       
   330 	    cap |= WLANCOND_OPEN;
       
   331 
       
   332 	if (cap & (WLANCOND_WPA_PSK | WLANCOND_WPA_EAP)) {
       
   333 	    Maemo::IAPConf saved_iap(iap_id);
       
   334 	    bool wpa2_only = saved_iap.value("EAP_wpa2_only_mode").toBool();
       
   335 	    if (wpa2_only) {
       
   336 		cap |= WLANCOND_WPA2;
       
   337 	    }
       
   338 	}
       
   339     }
       
   340 
       
   341     cap2nwattr(cap, &network_attr);
       
   342     if (is_iap_id)
       
   343 	network_attr |= ICD_NW_ATTR_IAPNAME;
       
   344 
       
   345     return (uint32_t)network_attr;
       
   346 }
       
   347 
       
   348 
       
   349 void QNetworkConfigurationManagerPrivate::addConfiguration(QString& iap_id)
       
   350 {
       
   351     // Note: When new IAP is created, this function gets called multiple times
       
   352     //       in a row.
       
   353     //       For example: Empty type & name for WLAN was stored into newly
       
   354     //                    created IAP data in gconf when this function gets
       
   355     //                    called for the first time.
       
   356     //                    WLAN type & name are updated into IAP data in gconf
       
   357     //                    as soon as WLAN connection is up and running.
       
   358     //                    => And this function gets called again.
       
   359 
       
   360     if (!accessPointConfigurations.contains(iap_id)) {
       
   361 	Maemo::IAPConf saved_iap(iap_id);
       
   362         QString iap_type = saved_iap.value("type").toString();
       
   363         QString iap_name = saved_iap.value("name").toString();
       
   364         QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
       
   365         if (!iap_type.isEmpty() && !iap_name.isEmpty()) {
       
   366             // Check if new IAP is actually Undefined WLAN configuration
       
   367             // Note: SSID is used as an iap id for Undefined WLAN configurations
       
   368             //       => configuration must be searched using SSID
       
   369             if (!ssid.isEmpty() && accessPointConfigurations.contains(ssid)) {
       
   370                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.take(ssid);
       
   371                 if (ptr.data()) {
       
   372                     ptr->id = iap_id;
       
   373                     ptr->iap_type = iap_type;
       
   374                     ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   375                     ptr->network_id = ssid;
       
   376                     ptr->service_id = saved_iap.value("service_id").toString();
       
   377                     ptr->service_type = saved_iap.value("service_type").toString();
       
   378                     if (m_onlineIapId == iap_id) {
       
   379                         ptr->state = QNetworkConfiguration::Active;
       
   380                     } else {
       
   381                         ptr->state = QNetworkConfiguration::Defined;
       
   382                     }
       
   383                     accessPointConfigurations.insert(iap_id, ptr);
       
   384                     configurationChanged(ptr.data());
       
   385                 }
       
   386             } else {
       
   387                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   388                 cpPriv->name = saved_iap.value("name").toString();
       
   389                 if (cpPriv->name.isEmpty())
       
   390                     cpPriv->name = iap_id;
       
   391                 cpPriv->isValid = true;
       
   392                 cpPriv->id = iap_id;
       
   393                 cpPriv->iap_type = iap_type;
       
   394                 cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   395                 cpPriv->service_id = saved_iap.value("service_id").toString();
       
   396                 cpPriv->service_type = saved_iap.value("service_type").toString();
       
   397                 if (iap_type.startsWith(QLatin1String("WLAN"))) {
       
   398                     QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
       
   399                     if (ssid.isEmpty()) {
       
   400                         qWarning() << "Cannot get ssid for" << iap_id;
       
   401                     }
       
   402                     cpPriv->network_id = ssid;
       
   403                 }
       
   404                 cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   405                 if (m_onlineIapId == iap_id) {
       
   406                     cpPriv->state = QNetworkConfiguration::Active;
       
   407                 } else {
       
   408                     cpPriv->state = QNetworkConfiguration::Defined;
       
   409                 }
       
   410                 cpPriv->manager = this;
       
   411 
       
   412                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   413                 accessPointConfigurations.insert(iap_id, ptr);
       
   414 
       
   415 #ifdef BEARER_MANAGEMENT_DEBUG
       
   416                 qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
       
   417 #endif
       
   418                 QNetworkConfiguration item;
       
   419                 item.d = ptr;
       
   420                 emit configurationAdded(item);
       
   421             }
       
   422         } else {
       
   423             qWarning("IAP %s does not have \"type\" or \"name\" fields defined, skipping this IAP.", iap_id.toAscii().data());
       
   424         }
       
   425     } else {
       
   426 #ifdef BEARER_MANAGEMENT_DEBUG
       
   427 	qDebug() << "IAP" << iap_id << "already in db.";
       
   428 #endif
       
   429 
       
   430 	/* Check if the data in db changed and update configuration accordingly
       
   431 	 */
       
   432         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iap_id);
       
   433 	if (ptr.data()) {
       
   434 	    Maemo::IAPConf changed_iap(iap_id);
       
   435 	    QString iap_type = changed_iap.value("type").toString();
       
   436 	    bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */
       
   437 
       
   438 	    ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   439 	    ptr->service_id = changed_iap.value("service_id").toString();
       
   440 	    ptr->service_type = changed_iap.value("service_type").toString();
       
   441 
       
   442 	    if (!iap_type.isEmpty()) {
       
   443 		ptr->name = changed_iap.value("name").toString();
       
   444 		if (ptr->name.isEmpty())
       
   445 		    ptr->name = iap_id;
       
   446 		ptr->isValid = true;
       
   447 		if (ptr->iap_type != iap_type) {
       
   448 		    ptr->iap_type = iap_type;
       
   449 		    update_needed = true;
       
   450 		}
       
   451         if (iap_type.startsWith(QLatin1String("WLAN"))) {
       
   452 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
       
   453 		    if (ssid.isEmpty()) {
       
   454 			qWarning() << "Cannot get ssid for" << iap_id;
       
   455 		    }
       
   456 		    if (ptr->network_id != ssid) {
       
   457                         ptr->network_id = ssid;
       
   458                         update_needed = true;
       
   459 		    }
       
   460 		}
       
   461 	    }
       
   462 	    if (update_needed) {
       
   463                 ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   464                 if (m_onlineIapId == iap_id) {
       
   465                     if (ptr->state < QNetworkConfiguration::Active) {
       
   466                         ptr->state = QNetworkConfiguration::Active;
       
   467                         configurationChanged(ptr.data());
       
   468                     }
       
   469                 } else if (ptr->state < QNetworkConfiguration::Defined) {
       
   470 		    ptr->state = QNetworkConfiguration::Defined;
       
   471                     configurationChanged(ptr.data());
       
   472                 }
       
   473 	    }
       
   474 	} else {
       
   475 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
       
   476 	}
       
   477     }
       
   478 }
       
   479 
       
   480 void QNetworkConfigurationManagerPrivate::updateConfigurations()
       
   481 {
       
   482     doUpdateConfigurations();
       
   483 }
       
   484 
       
   485 void QNetworkConfigurationManagerPrivate::doUpdateConfigurations(QList<Maemo::IcdScanResult> scanned)
       
   486 {
       
   487     /* Contains all known iap_ids from storage */
       
   488     QList<QString> knownConfigs = accessPointConfigurations.keys();
       
   489 
       
   490     /* Contains all known WLAN network ids (like ssid) from storage */
       
   491     QMultiHash<QByteArray, SSIDInfo* > notDiscoveredWLANConfigs;
       
   492 
       
   493     QList<QString> all_iaps;
       
   494     Maemo::IAPConf::getAll(all_iaps);
       
   495 
       
   496     foreach (const QString &iap_id, all_iaps) {
       
   497 	QByteArray ssid;
       
   498 
       
   499 	Maemo::IAPConf saved_ap(iap_id);
       
   500 	bool is_temporary = saved_ap.value("temporary").toBool();
       
   501     if (is_temporary) {
       
   502 #ifdef BEARER_MANAGEMENT_DEBUG
       
   503 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
       
   504 #endif
       
   505 	    continue;
       
   506 	}
       
   507 
       
   508 	QString iap_type = saved_ap.value("type").toString();
       
   509     if (iap_type.startsWith(QLatin1String("WLAN"))) {
       
   510 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
       
   511 	    if (ssid.isEmpty()) {
       
   512 		qWarning() << "Cannot get ssid for" << iap_id;
       
   513 		continue;
       
   514 	    }
       
   515 
       
   516 	    QString security_method = saved_ap.value("wlan_security").toString();
       
   517 	    SSIDInfo *info = new SSIDInfo;
       
   518 	    info->iap_id = iap_id;
       
   519 	    info->wlan_security = security_method;
       
   520             notDiscoveredWLANConfigs.insert(ssid, info);
       
   521 	} else if (iap_type.isEmpty()) {
       
   522 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
       
   523 	    continue;
       
   524 	} else {
       
   525 #ifdef BEARER_MANAGEMENT_DEBUG
       
   526 	    qDebug() << "IAP" << iap_id << "network type is" << iap_type;
       
   527 #endif
       
   528 	    ssid.clear();
       
   529 	}
       
   530 
       
   531 	if (!accessPointConfigurations.contains(iap_id)) {
       
   532 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   533 	    cpPriv->name = saved_ap.value("name").toString();
       
   534 	    if (cpPriv->name.isEmpty()) {
       
   535 		if (!ssid.isEmpty() && ssid.size() > 0)
       
   536 		    cpPriv->name = ssid.data();
       
   537 		else
       
   538 		    cpPriv->name = iap_id;
       
   539 	    }
       
   540             cpPriv->isValid = true;
       
   541 	    cpPriv->id = iap_id;
       
   542 	    cpPriv->network_id = ssid;
       
   543 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   544 	    cpPriv->iap_type = iap_type;
       
   545 	    cpPriv->service_id = saved_ap.value("service_id").toString();
       
   546 	    cpPriv->service_type = saved_ap.value("service_type").toString();
       
   547 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   548 	    cpPriv->state = QNetworkConfiguration::Defined;
       
   549 	    cpPriv->manager = this;
       
   550 
       
   551 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   552 	    accessPointConfigurations.insert(iap_id, ptr);
       
   553 
       
   554 #ifdef BEARER_MANAGEMENT_DEBUG
       
   555 	    qDebug("IAP: %s, name: %s, ssid: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
       
   556 #endif
       
   557 	} else {
       
   558             knownConfigs.removeOne(iap_id);
       
   559 #ifdef BEARER_MANAGEMENT_DEBUG
       
   560 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
       
   561 #endif
       
   562 	}
       
   563     }
       
   564 
       
   565     /* This is skipped in the first update as scanned size is zero */
       
   566     if (!scanned.isEmpty())
       
   567       for (int i=0; i<scanned.size(); ++i) {
       
   568 	const Maemo::IcdScanResult ap = scanned.at(i); 
       
   569 
       
   570 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
       
   571 	    /* The network_id is IAP id, so the IAP is a known one */
       
   572 	    QString iapid = ap.scan.network_id.data();
       
   573             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iapid);
       
   574 	    if (priv.data()) {
       
   575                 bool stateChanged = false;
       
   576                 // Check if state is not already Discovered or Active
       
   577                 if (priv->state < QNetworkConfiguration::Discovered) {
       
   578                     priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */
       
   579                     stateChanged = true;
       
   580                 }
       
   581 		priv->network_attrs = ap.scan.network_attrs;
       
   582 		priv->service_id = ap.scan.service_id;
       
   583 		priv->service_type = ap.scan.service_type;
       
   584 		priv->service_attrs = ap.scan.service_attrs;
       
   585 
       
   586                 if (stateChanged) {
       
   587                     configurationChanged(priv.data());
       
   588                 }
       
   589 #ifdef BEARER_MANAGEMENT_DEBUG
       
   590 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
       
   591 #endif
       
   592 
       
   593         if (!ap.scan.network_type.startsWith(QLatin1String("WLAN")))
       
   594 		    continue; // not a wlan AP
       
   595 
       
   596                 /* Remove scanned AP from discovered WLAN configurations so that we can
       
   597 		 * emit configurationRemoved signal later
       
   598 		 */
       
   599                 QList<SSIDInfo* > known_iaps = notDiscoveredWLANConfigs.values(priv->network_id);
       
   600 	    rescan_list:
       
   601 		if (!known_iaps.isEmpty()) {
       
   602 		    for (int k=0; k<known_iaps.size(); ++k) {
       
   603 			SSIDInfo *iap = known_iaps.at(k);
       
   604 
       
   605 #ifdef BEARER_MANAGEMENT_DEBUG
       
   606 			//qDebug() << "iap" << iap->iap_id << "security" << iap->wlan_security << "scan" << network_attrs_to_security(ap.scan.network_attrs);
       
   607 #endif
       
   608 
       
   609 			if (iap->wlan_security == 
       
   610 			    network_attrs_to_security(ap.scan.network_attrs)) {
       
   611 			    /* Remove IAP from the list */
       
   612                             notDiscoveredWLANConfigs.remove(priv->network_id, iap);
       
   613 #ifdef BEARER_MANAGEMENT_DEBUG
       
   614 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
       
   615 #endif
       
   616 			    known_iaps.removeAt(k);
       
   617 			    delete iap;
       
   618 			    goto rescan_list;
       
   619 			}
       
   620 		    }
       
   621 		}
       
   622 	    } else {
       
   623 		qWarning() << "IAP" << iapid << "is missing in configuration.";
       
   624 	    }
       
   625 
       
   626 	} else {
       
   627             /* Non saved access point data */
       
   628 	    QByteArray scanned_ssid = ap.scan.network_id;
       
   629             if (!accessPointConfigurations.contains(scanned_ssid)) {
       
   630                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   631                 QString hrs = scanned_ssid.data();
       
   632 
       
   633                 cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
       
   634                 cpPriv->isValid = true;
       
   635                 cpPriv->id = scanned_ssid.data();  // Note: id is now ssid, it should be set to IAP id if the IAP is saved
       
   636                 cpPriv->network_id = scanned_ssid;
       
   637                 cpPriv->iap_type = ap.scan.network_type;
       
   638                 cpPriv->network_attrs = ap.scan.network_attrs;
       
   639                 cpPriv->service_id = ap.scan.service_id;
       
   640                 cpPriv->service_type = ap.scan.service_type;
       
   641                 cpPriv->service_attrs = ap.scan.service_attrs;
       
   642                 cpPriv->manager = this;
       
   643 
       
   644                 cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   645                 cpPriv->state = QNetworkConfiguration::Undefined;
       
   646 
       
   647                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   648                 accessPointConfigurations.insert(cpPriv->id, ptr);
       
   649 
       
   650     #ifdef BEARER_MANAGEMENT_DEBUG
       
   651                 qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
       
   652     #endif
       
   653 
       
   654                 QNetworkConfiguration item;
       
   655                 item.d = ptr;
       
   656                 emit configurationAdded(item);
       
   657             } else {
       
   658                 knownConfigs.removeOne(scanned_ssid);
       
   659             }
       
   660         }
       
   661     }
       
   662 
       
   663     if (!firstUpdate) {
       
   664         // Update Defined status to all defined WLAN IAPs which
       
   665         // could not be found when access points were scanned
       
   666         QHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
       
   667 	while (i.hasNext()) {
       
   668 	    i.next();
       
   669 	    SSIDInfo *iap = i.value();
       
   670 	    QString iap_id = iap->iap_id;
       
   671 	    //qDebug() << i.key() << ": " << iap_id;
       
   672 
       
   673             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iap_id);
       
   674 	    if (priv.data()) {
       
   675                 // WLAN AccessPoint configuration could not be Discovered
       
   676                 // => Make sure that configuration state is Defined
       
   677                 if (priv->state > QNetworkConfiguration::Defined) {
       
   678                     priv->state = QNetworkConfiguration::Defined;
       
   679                     configurationChanged(priv.data());
       
   680                 }
       
   681 	    }
       
   682 	}
       
   683 
       
   684         /* Remove non existing iaps since last update */
       
   685         foreach (const QString &oldIface, knownConfigs) {
       
   686             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
       
   687             if (priv.data()) {
       
   688                 priv->isValid = false;
       
   689                 QNetworkConfiguration item;
       
   690                 item.d = priv;
       
   691                 emit configurationRemoved(item);
       
   692 		//if we would have SNAP support we would have to remove the references
       
   693 		//from existing ServiceNetworks to the removed access point configuration
       
   694             }
       
   695         }
       
   696     }
       
   697 
       
   698     QMutableHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
       
   699     while (i.hasNext()) {
       
   700 	i.next();
       
   701 	SSIDInfo *iap = i.value();
       
   702 	delete iap;
       
   703 	i.remove();
       
   704     }
       
   705 
       
   706     if (!firstUpdate)
       
   707 	emit configurationUpdateComplete();
       
   708 
       
   709     if (firstUpdate)
       
   710         firstUpdate = false;
       
   711 }
       
   712 
       
   713 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
       
   714 {
       
   715     /* Here we just return [ANY] request to icd and let the icd decide which
       
   716      * IAP to connect.
       
   717      */
       
   718     QNetworkConfiguration item;
       
   719     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
       
   720         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
       
   721     return item;
       
   722 }
       
   723 
       
   724 void QNetworkConfigurationManagerPrivate::startListeningStateSignalsForAllConnections()
       
   725 {
       
   726     // Start listening ICD_DBUS_API_STATE_SIG signals
       
   727     m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
       
   728                                           ICD_DBUS_API_PATH,
       
   729                                           ICD_DBUS_API_INTERFACE,
       
   730                                           ICD_DBUS_API_STATE_SIG,
       
   731                                           this, SLOT(connectionStateSignalsSlot(QDBusMessage)));
       
   732 
       
   733     // Calling ICD_DBUS_API_STATE_REQ makes sure that initial state will be updated immediately
       
   734     m_gettingInitialConnectionState = true;
       
   735     m_dbusInterface->call(ICD_DBUS_API_STATE_REQ);
       
   736 }
       
   737 
       
   738 void QNetworkConfigurationManagerPrivate::connectionStateSignalsSlot(QDBusMessage msg)
       
   739 {
       
   740     QList<QVariant> arguments = msg.arguments();
       
   741     if (arguments[1].toUInt() != 0 || arguments.count() < 8) {
       
   742         return;
       
   743     }
       
   744 
       
   745     QString iapid = arguments[5].toByteArray().data();
       
   746     uint icd_connection_state = arguments[7].toUInt();
       
   747 
       
   748     switch (icd_connection_state) {
       
   749     case ICD_STATE_CONNECTED:
       
   750         {
       
   751         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iapid);
       
   752         if (ptr.data()) {
       
   753             ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   754             if (ptr->state != QNetworkConfiguration::Active) {
       
   755                 ptr->state = QNetworkConfiguration::Active;
       
   756                 if (!m_gettingInitialConnectionState) {
       
   757                     configurationChanged(ptr.data());
       
   758                     if (m_onlineIapId.isEmpty()) {
       
   759                         emit onlineStateChanged(true);
       
   760                     }
       
   761                 }
       
   762                 m_onlineIapId = iapid;
       
   763             }
       
   764         } else {
       
   765             // This gets called when new WLAN IAP is created using Connection dialog
       
   766             // At this point Undefined WLAN configuration has SSID as iap id
       
   767             // => Because of that configuration can not be found from
       
   768             //    accessPointConfigurations using correct iap id
       
   769             emit onlineStateChanged(true);
       
   770             m_onlineIapId = iapid;
       
   771         }
       
   772         break;
       
   773         }
       
   774     case ICD_STATE_DISCONNECTED:
       
   775         {
       
   776         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iapid);
       
   777         if (ptr.data()) {
       
   778             ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   779             if (ptr->state == QNetworkConfiguration::Active) {
       
   780                 ptr->state = QNetworkConfiguration::Discovered;
       
   781                 if (!m_gettingInitialConnectionState) {
       
   782                     configurationChanged(ptr.data());
       
   783 
       
   784                     // Note: If ICD switches used IAP from one to another:
       
   785                     //       1) new IAP is reported to be online first
       
   786                     //       2) old IAP is reported to be offline then
       
   787                     // => Device can be reported to be offline only
       
   788                     //    if last known online IAP is reported to be disconnected
       
   789                     if (iapid == m_onlineIapId) {
       
   790                         // It's known that there is only one global ICD connection
       
   791                         // => Because ICD state was reported to be DISCONNECTED, Device is offline
       
   792                         m_onlineIapId.clear();
       
   793                         emit onlineStateChanged(false);
       
   794                     }
       
   795                 }
       
   796             }
       
   797         } else {
       
   798             // Disconnected IAP was not found from accessPointConfigurations
       
   799             // => Reason: Online IAP was removed which resulted ICD to disconnect
       
   800             if (iapid == m_onlineIapId) {
       
   801                 // It's known that there is only one global ICD connection
       
   802                 // => Because ICD state was reported to be DISCONNECTED, Device is offline
       
   803                 m_onlineIapId.clear();
       
   804                 emit onlineStateChanged(false);
       
   805             }
       
   806         }
       
   807         break;
       
   808         }
       
   809     default:
       
   810         break;
       
   811     }
       
   812     
       
   813     emit iapStateChanged(iapid, icd_connection_state);
       
   814 
       
   815     m_gettingInitialConnectionState = false;
       
   816 }
       
   817 
       
   818 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
       
   819 {
       
   820     if (m_scanGoingOn) {
       
   821         return;
       
   822     }
       
   823     m_scanGoingOn = true;
       
   824 
       
   825     m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
       
   826                                           ICD_DBUS_API_PATH,
       
   827                                           ICD_DBUS_API_INTERFACE,
       
   828                                           ICD_DBUS_API_SCAN_SIG,
       
   829                                           this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage)));
       
   830 
       
   831     QDBusMessage msg = m_dbusInterface->call(ICD_DBUS_API_SCAN_REQ,
       
   832                                              (uint)ICD_SCAN_REQUEST_ACTIVE);
       
   833     m_typesToBeScanned = msg.arguments()[0].value<QStringList>();
       
   834     m_scanTimer.start(ICD_SHORT_SCAN_TIMEOUT);
       
   835 }
       
   836 
       
   837 void QNetworkConfigurationManagerPrivate::cancelAsyncConfigurationUpdate()
       
   838 {
       
   839     if (!m_scanGoingOn) {
       
   840         return;
       
   841     }
       
   842     m_scanGoingOn = false;
       
   843 
       
   844     if (m_scanTimer.isActive()) {
       
   845         m_scanTimer.stop();
       
   846     }
       
   847 
       
   848     m_dbusInterface->connection().disconnect(ICD_DBUS_API_INTERFACE,
       
   849                                              ICD_DBUS_API_PATH,
       
   850                                              ICD_DBUS_API_INTERFACE,
       
   851                                              ICD_DBUS_API_SCAN_SIG,
       
   852                                              this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage)));
       
   853 
       
   854     // Stop scanning rounds by calling ICD_DBUS_API_SCAN_CANCEL
       
   855     // <=> If ICD_DBUS_API_SCAN_CANCEL is not called, new scanning round will
       
   856     //     be started after the module scan timeout.
       
   857     m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
       
   858 }
       
   859 
       
   860 void QNetworkConfigurationManagerPrivate::finishAsyncConfigurationUpdate()
       
   861 {
       
   862     cancelAsyncConfigurationUpdate();
       
   863     doUpdateConfigurations(m_scanResult);
       
   864     m_scanResult.clear();
       
   865 }
       
   866 
       
   867 void QNetworkConfigurationManagerPrivate::asyncUpdateConfigurationsSlot(QDBusMessage msg)
       
   868 {
       
   869     QList<QVariant> arguments = msg.arguments();
       
   870     uint icd_scan_status = arguments.takeFirst().toUInt();
       
   871     if (icd_scan_status == ICD_SCAN_COMPLETE) {
       
   872         m_typesToBeScanned.removeOne(arguments[6].toString());
       
   873         if (!m_typesToBeScanned.count()) {
       
   874             finishAsyncConfigurationUpdate();
       
   875         }
       
   876     } else {
       
   877         Maemo::IcdScanResult scanResult;
       
   878         scanResult.status = icd_scan_status;
       
   879         scanResult.timestamp = arguments.takeFirst().toUInt();
       
   880         scanResult.scan.service_type = arguments.takeFirst().toString();
       
   881         scanResult.service_name = arguments.takeFirst().toString();
       
   882         scanResult.scan.service_attrs = arguments.takeFirst().toUInt();
       
   883         scanResult.scan.service_id = arguments.takeFirst().toString();
       
   884         scanResult.service_priority = arguments.takeFirst().toInt();
       
   885         scanResult.scan.network_type = arguments.takeFirst().toString();
       
   886         scanResult.network_name = arguments.takeFirst().toString();
       
   887         scanResult.scan.network_attrs = arguments.takeFirst().toUInt();
       
   888         scanResult.scan.network_id = arguments.takeFirst().toByteArray();
       
   889         scanResult.network_priority = arguments.takeFirst().toInt();
       
   890         scanResult.signal_strength = arguments.takeFirst().toInt();
       
   891         scanResult.station_id = arguments.takeFirst().toString();
       
   892         scanResult.signal_dB = arguments.takeFirst().toInt();
       
   893 
       
   894         m_scanResult.append(scanResult);
       
   895     }
       
   896 }
       
   897 
       
   898 void QNetworkConfigurationManagerPrivate::cleanup()
       
   899 {
       
   900     if (m_scanGoingOn) {
       
   901         m_scanTimer.stop();
       
   902         m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
       
   903     }
       
   904     iapMonitor()->cleanup();
       
   905 }
       
   906 
       
   907 #include "qnetworkconfigmanager_maemo.moc"
       
   908 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
       
   909 
       
   910 QTM_END_NAMESPACE