qtmobility/src/bearer/qnetworkconfigmanager_maemo.cpp
changeset 0 cfcbf08528c4
child 2 5822d84012fb
child 4 90517678cc4f
equal deleted inserted replaced
-1:000000000000 0:cfcbf08528c4
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 
       
   210 
       
   211 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
       
   212 {
       
   213     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
       
   214     capFlags |= QNetworkConfigurationManager::DataStatistics;
       
   215     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
       
   216 }
       
   217 
       
   218 
       
   219 static inline QString network_attrs_to_security(uint network_attrs)
       
   220 {
       
   221     uint cap = 0;
       
   222     nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
       
   223     if (cap & WLANCOND_OPEN)
       
   224 	return "NONE";
       
   225     else if (cap & WLANCOND_WEP)
       
   226 	return "WEP";
       
   227     else if (cap & WLANCOND_WPA_PSK)
       
   228 	return "WPA_PSK";
       
   229     else if (cap & WLANCOND_WPA_EAP)
       
   230 	return "WPA_EAP";
       
   231     return "";
       
   232 }
       
   233 
       
   234 
       
   235 struct SSIDInfo {
       
   236     QString iap_id;
       
   237     QString wlan_security;
       
   238 };
       
   239 
       
   240 
       
   241 void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivate *ptr)
       
   242 {
       
   243     QNetworkConfiguration item;
       
   244     item.d = ptr;
       
   245     emit configurationChanged(item);
       
   246 }
       
   247 
       
   248 void QNetworkConfigurationManagerPrivate::deleteConfiguration(QString& iap_id)
       
   249 {
       
   250     /* Called when IAPs are deleted in db, in this case we do not scan
       
   251      * or read all the IAPs from db because it might take too much power
       
   252      * (multiple applications would need to scan and read all IAPs from db)
       
   253      */
       
   254     if (accessPointConfigurations.contains(iap_id)) {
       
   255 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iap_id);
       
   256 	if (priv.data()) {
       
   257 	    priv->isValid = false;
       
   258 #ifdef BEARER_MANAGEMENT_DEBUG
       
   259 	    qDebug() << "IAP" << iap_id << "was removed from storage.";
       
   260 #endif
       
   261 
       
   262 	    QNetworkConfiguration item;
       
   263 	    item.d = priv;
       
   264 	    emit configurationRemoved(item);
       
   265 	    configChanged(priv.data(), false);
       
   266 	} else
       
   267 	    qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
       
   268     } else {
       
   269 #ifdef BEARER_MANAGEMENT_DEBUG
       
   270 	qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
       
   271 #endif
       
   272     }
       
   273 }
       
   274 
       
   275 
       
   276 uint32_t QNetworkConfigurationManagerPrivate::getNetworkAttrs(bool is_iap_id,
       
   277 							    QString& iap_id,
       
   278 							    QString& iap_type,
       
   279 							    QString security_method)
       
   280 {
       
   281     guint network_attr = 0;
       
   282     dbus_uint32_t cap = 0;
       
   283 
       
   284     if (iap_type == "WLAN_INFRA")
       
   285 	cap |= WLANCOND_INFRA;
       
   286     else if (iap_type == "WLAN_ADHOC")
       
   287 	cap |= WLANCOND_ADHOC;
       
   288 
       
   289     if (security_method.isEmpty() && (cap & (WLANCOND_INFRA | WLANCOND_ADHOC))) {
       
   290 	Maemo::IAPConf saved_ap(iap_id);
       
   291 	security_method = saved_ap.value("wlan_security").toString();
       
   292     }
       
   293 
       
   294     if (!security_method.isEmpty()) {
       
   295 	if (security_method == "WEP")
       
   296 	    cap |= WLANCOND_WEP;
       
   297 	else if (security_method == "WPA_PSK")
       
   298 	    cap |= WLANCOND_WPA_PSK;
       
   299 	else if (security_method == "WPA_EAP")
       
   300 	    cap |= WLANCOND_WPA_EAP;
       
   301 	else if (security_method == "NONE")
       
   302 	    cap |= WLANCOND_OPEN;
       
   303 
       
   304 	if (cap & (WLANCOND_WPA_PSK | WLANCOND_WPA_EAP)) {
       
   305 	    Maemo::IAPConf saved_iap(iap_id);
       
   306 	    bool wpa2_only = saved_iap.value("EAP_wpa2_only_mode").toBool();
       
   307 	    if (wpa2_only) {
       
   308 		cap |= WLANCOND_WPA2;
       
   309 	    }
       
   310 	}
       
   311     }
       
   312 
       
   313     cap2nwattr(cap, &network_attr);
       
   314     if (is_iap_id)
       
   315 	network_attr |= ICD_NW_ATTR_IAPNAME;
       
   316 
       
   317     return (uint32_t)network_attr;
       
   318 }
       
   319 
       
   320 
       
   321 void QNetworkConfigurationManagerPrivate::addConfiguration(QString& iap_id)
       
   322 {
       
   323     if (!accessPointConfigurations.contains(iap_id)) {
       
   324 	Maemo::IAPConf saved_iap(iap_id);
       
   325 	QString iap_type = saved_iap.value("type").toString();
       
   326 	if (!iap_type.isEmpty()) {
       
   327 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   328 	    cpPriv->name = saved_iap.value("name").toString();
       
   329 	    if (cpPriv->name.isEmpty())
       
   330 		cpPriv->name = iap_id;
       
   331 	    cpPriv->isValid = true;
       
   332 	    cpPriv->id = iap_id;
       
   333 	    cpPriv->iap_type = iap_type;
       
   334 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   335 	    cpPriv->service_id = saved_iap.value("service_id").toString();
       
   336 	    cpPriv->service_type = saved_iap.value("service_type").toString();
       
   337 	    if (iap_type.startsWith("WLAN")) {
       
   338 		QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
       
   339 		if (ssid.isEmpty()) {
       
   340 		    qWarning() << "Cannot get ssid for" << iap_id;
       
   341 		}
       
   342 	    }
       
   343 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   344 	    cpPriv->state = QNetworkConfiguration::Defined;
       
   345 
       
   346 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   347 	    accessPointConfigurations.insert(iap_id, ptr);
       
   348 
       
   349 #ifdef BEARER_MANAGEMENT_DEBUG
       
   350 	    qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
       
   351 #endif
       
   352 
       
   353 	    QNetworkConfiguration item;
       
   354 	    item.d = ptr;
       
   355 	    emit configurationAdded(item);
       
   356 	    configChanged(ptr.data(), true);
       
   357 	} else {
       
   358 	    qWarning("IAP %s does not have \"type\" field defined, skipping this IAP.", iap_id.toAscii().data());
       
   359 	}
       
   360     } else {
       
   361 #ifdef BEARER_MANAGEMENT_DEBUG
       
   362 	qDebug() << "IAP" << iap_id << "already in db.";
       
   363 #endif
       
   364 
       
   365 	/* Check if the data in db changed and update configuration accordingly
       
   366 	 */
       
   367 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.take(iap_id);
       
   368 	if (ptr.data()) {
       
   369 	    Maemo::IAPConf changed_iap(iap_id);
       
   370 	    QString iap_type = changed_iap.value("type").toString();
       
   371 	    bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */
       
   372 
       
   373 	    ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   374 	    ptr->service_id = changed_iap.value("service_id").toString();
       
   375 	    ptr->service_type = changed_iap.value("service_type").toString();
       
   376 
       
   377 	    if (!iap_type.isEmpty()) {
       
   378 		ptr->name = changed_iap.value("name").toString();
       
   379 		if (ptr->name.isEmpty())
       
   380 		    ptr->name = iap_id;
       
   381 		ptr->isValid = true;
       
   382 		if (ptr->iap_type != iap_type) {
       
   383 		    ptr->iap_type = iap_type;
       
   384 		    update_needed = true;
       
   385 		}
       
   386 		if (iap_type.startsWith("WLAN")) {
       
   387 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
       
   388 		    if (ssid.isEmpty()) {
       
   389 			qWarning() << "Cannot get ssid for" << iap_id;
       
   390 		    }
       
   391 		    if (ptr->network_id != ssid) {
       
   392 			ptr->network_id = ssid;
       
   393 			update_needed = true;
       
   394 		    }
       
   395 		}
       
   396 	    }
       
   397 	    accessPointConfigurations.insert(iap_id, ptr);
       
   398 	    if (update_needed) {
       
   399 		ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   400 		if (ptr->state != QNetworkConfiguration::Defined) {
       
   401 		    ptr->state = QNetworkConfiguration::Defined;
       
   402 		    configurationChanged(ptr.data());
       
   403 		}
       
   404 	    }
       
   405 	} else {
       
   406 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
       
   407 	}
       
   408     }
       
   409 }
       
   410 
       
   411 
       
   412 void QNetworkConfigurationManagerPrivate::updateConfigurations()
       
   413 {
       
   414     /* Contains known network id (like ssid) from storage */
       
   415     QMultiHash<QByteArray, SSIDInfo* > knownConfigs;
       
   416 
       
   417     /* All the scanned access points */
       
   418     QList<Maemo::IcdScanResult> scanned;
       
   419 
       
   420     /* Turn on IAP monitoring */
       
   421     iapMonitor()->setup(this);
       
   422 
       
   423     if (firstUpdate) {
       
   424 	/* We create a default configuration which is a pseudo config */
       
   425 	QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   426 	cpPriv->name = "UserChoice";
       
   427 	cpPriv->state = QNetworkConfiguration::Discovered;
       
   428 	cpPriv->isValid = true;
       
   429 	cpPriv->id = OSSO_IAP_ANY;
       
   430 	cpPriv->type = QNetworkConfiguration::UserChoice;
       
   431 	cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
       
   432 	cpPriv->roamingSupported = false;
       
   433 	cpPriv->manager = this;
       
   434 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   435 	userChoiceConfigurations.insert(cpPriv->id, ptr);
       
   436     }
       
   437 
       
   438     /* We return currently configured IAPs in the first run and do the WLAN
       
   439      * scan in subsequent runs.
       
   440      */
       
   441     QList<QString> all_iaps;
       
   442     Maemo::IAPConf::getAll(all_iaps);
       
   443 
       
   444     foreach (QString iap_id, all_iaps) {
       
   445 	QByteArray ssid;
       
   446 
       
   447 	Maemo::IAPConf saved_ap(iap_id);
       
   448 	bool is_temporary = saved_ap.value("temporary").toBool();
       
   449 	if (is_temporary) {
       
   450 #ifdef BEARER_MANAGEMENT_DEBUG
       
   451 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
       
   452 #endif
       
   453 	    continue;
       
   454 	}
       
   455 
       
   456 	QString iap_type = saved_ap.value("type").toString();
       
   457 	if (iap_type.startsWith("WLAN")) {
       
   458 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
       
   459 	    if (ssid.isEmpty()) {
       
   460 		qWarning() << "Cannot get ssid for" << iap_id;
       
   461 		continue;
       
   462 	    }
       
   463 
       
   464 	    QString security_method = saved_ap.value("wlan_security").toString();
       
   465 	    SSIDInfo *info = new SSIDInfo;
       
   466 	    info->iap_id = iap_id;
       
   467 	    info->wlan_security = security_method;
       
   468 	    knownConfigs.insert(ssid, info);
       
   469 	} else if (iap_type.isEmpty()) {
       
   470 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
       
   471 	    continue;
       
   472 	} else {
       
   473 #ifdef BEARER_MANAGEMENT_DEBUG
       
   474 	    qDebug() << "IAP" << iap_id << "network type is" << iap_type;
       
   475 #endif
       
   476 	    ssid.clear();
       
   477 	}
       
   478 
       
   479 	if (!accessPointConfigurations.contains(iap_id)) {
       
   480 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   481 	    cpPriv->name = saved_ap.value("name").toString();
       
   482 	    if (cpPriv->name.isEmpty()) {
       
   483 		if (!ssid.isEmpty() && ssid.size() > 0)
       
   484 		    cpPriv->name = ssid.data();
       
   485 		else
       
   486 		    cpPriv->name = iap_id;
       
   487 	    }
       
   488 	    cpPriv->isValid = true;
       
   489 	    cpPriv->id = iap_id;
       
   490 	    cpPriv->network_id = ssid;
       
   491 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
       
   492 	    cpPriv->iap_type = iap_type;
       
   493 	    cpPriv->service_id = saved_ap.value("service_id").toString();
       
   494 	    cpPriv->service_type = saved_ap.value("service_type").toString();
       
   495 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   496 	    cpPriv->state = QNetworkConfiguration::Defined;
       
   497 	    cpPriv->manager = this;
       
   498 
       
   499 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   500 	    accessPointConfigurations.insert(iap_id, ptr);
       
   501 
       
   502 #ifdef BEARER_MANAGEMENT_DEBUG
       
   503 	    qDebug("IAP: %s, name: %s, ssid: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
       
   504 #endif
       
   505 	} else {
       
   506 #ifdef BEARER_MANAGEMENT_DEBUG
       
   507 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
       
   508 #endif
       
   509 	}
       
   510     }
       
   511 
       
   512     if (!firstUpdate) {
       
   513 	QStringList scannedNetworkTypes;
       
   514 	QStringList networkTypesToScan;
       
   515 	QString error;
       
   516 	Maemo::Icd icd(ICD_SHORT_SCAN_TIMEOUT);
       
   517 
       
   518 	scannedNetworkTypes = icd.scan(ICD_SCAN_REQUEST_ACTIVE,
       
   519 				    networkTypesToScan,
       
   520 				    scanned,
       
   521 				    error);
       
   522 	if (!error.isEmpty()) {
       
   523 	    qWarning() << "Network scanning failed" << error;
       
   524 	} else {
       
   525 #ifdef BEARER_MANAGEMENT_DEBUG
       
   526 	    if (!scanned.isEmpty())
       
   527 		qDebug() << "Scan returned" << scanned.size() << "networks";
       
   528 	    else
       
   529 		qDebug() << "Scan returned nothing.";
       
   530 #endif
       
   531 	}
       
   532     }
       
   533 
       
   534 
       
   535     /* This is skipped in the first update as scanned size is zero */
       
   536     if (!scanned.isEmpty())
       
   537       for (int i=0; i<scanned.size(); ++i) {
       
   538 	const Maemo::IcdScanResult ap = scanned.at(i); 
       
   539 
       
   540 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
       
   541 	    /* The network_id is IAP id, so the IAP is a known one */
       
   542 	    QString iapid = ap.scan.network_id.data();
       
   543 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iapid);
       
   544 	    if (priv.data()) {
       
   545 		priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */
       
   546 		priv->network_attrs = ap.scan.network_attrs;
       
   547 		priv->service_id = ap.scan.service_id;
       
   548 		priv->service_type = ap.scan.service_type;
       
   549 		priv->service_attrs = ap.scan.service_attrs;
       
   550 
       
   551 		configurationChanged(priv.data());
       
   552 		accessPointConfigurations.insert(iapid, priv);
       
   553 #ifdef BEARER_MANAGEMENT_DEBUG
       
   554 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
       
   555 #endif
       
   556 
       
   557 		if (!ap.scan.network_type.startsWith("WLAN"))
       
   558 		    continue; // not a wlan AP
       
   559 
       
   560 		/* Remove scanned AP from known configurations so that we can
       
   561 		 * emit configurationRemoved signal later
       
   562 		 */
       
   563 		QList<SSIDInfo* > known_iaps = knownConfigs.values(priv->network_id);
       
   564 	    rescan_list:
       
   565 		if (!known_iaps.isEmpty()) {
       
   566 		    for (int k=0; k<known_iaps.size(); ++k) {
       
   567 			SSIDInfo *iap = known_iaps.at(k);
       
   568 
       
   569 #ifdef BEARER_MANAGEMENT_DEBUG
       
   570 			//qDebug() << "iap" << iap->iap_id << "security" << iap->wlan_security << "scan" << network_attrs_to_security(ap.scan.network_attrs);
       
   571 #endif
       
   572 
       
   573 			if (iap->wlan_security == 
       
   574 			    network_attrs_to_security(ap.scan.network_attrs)) {
       
   575 			    /* Remove IAP from the list */
       
   576 			    knownConfigs.remove(priv->network_id, iap);
       
   577 #ifdef BEARER_MANAGEMENT_DEBUG
       
   578 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
       
   579 #endif
       
   580 			    known_iaps.removeAt(k);
       
   581 			    delete iap;
       
   582 			    goto rescan_list;
       
   583 			}
       
   584 		    }
       
   585 		}
       
   586 	    } else {
       
   587 		qWarning() << "IAP" << iapid << "is missing in configuration.";
       
   588 	    }
       
   589 
       
   590 	} else {
       
   591 	    /* Non saved access point data */
       
   592 	    QByteArray scanned_ssid = ap.scan.network_id;
       
   593 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   594 	    QString hrs = scanned_ssid.data();
       
   595 
       
   596 	    cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
       
   597 	    cpPriv->isValid = true;
       
   598 	    cpPriv->id = scanned_ssid.data();  // Note: id is now ssid, it should be set to IAP id if the IAP is saved
       
   599 	    cpPriv->network_id = scanned_ssid;
       
   600 	    cpPriv->iap_type = ap.scan.network_type;
       
   601 	    cpPriv->network_attrs = ap.scan.network_attrs;
       
   602 	    cpPriv->service_id = ap.scan.service_id;
       
   603 	    cpPriv->service_type = ap.scan.service_type;
       
   604 	    cpPriv->service_attrs = ap.scan.service_attrs;
       
   605 	    cpPriv->manager = this;
       
   606 
       
   607 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   608 	    cpPriv->state = QNetworkConfiguration::Undefined;
       
   609 
       
   610 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   611 	    accessPointConfigurations.insert(cpPriv->id, ptr);
       
   612 
       
   613 #ifdef BEARER_MANAGEMENT_DEBUG
       
   614 	    qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
       
   615 #endif
       
   616 
       
   617 	    QNetworkConfiguration item;
       
   618 	    item.d = ptr;
       
   619 	    emit configurationAdded(item);
       
   620 	}
       
   621       }
       
   622 
       
   623 
       
   624     /* Remove non existing iaps since last update */
       
   625     if (!firstUpdate) {
       
   626 	QHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
       
   627 	while (i.hasNext()) {
       
   628 	    i.next();
       
   629 	    SSIDInfo *iap = i.value();
       
   630 	    QString iap_id = iap->iap_id;
       
   631 	    //qDebug() << i.key() << ": " << iap_id;
       
   632 
       
   633 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iap_id);
       
   634 	    if (priv.data()) {
       
   635 		priv->isValid = false;
       
   636 #ifdef BEARER_MANAGEMENT_DEBUG
       
   637 		qDebug() << "IAP" << iap_id << "was removed as it was not found in scan.";
       
   638 #endif
       
   639 
       
   640 		QNetworkConfiguration item;
       
   641 		item.d = priv;
       
   642 		emit configurationRemoved(item);
       
   643 		configChanged(priv.data(), false);
       
   644 
       
   645 		//if we would have SNAP support we would have to remove the references
       
   646 		//from existing ServiceNetworks to the removed access point configuration
       
   647 	    }
       
   648 	}
       
   649     }
       
   650 
       
   651 
       
   652     QMutableHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
       
   653     while (i.hasNext()) {
       
   654 	i.next();
       
   655 	SSIDInfo *iap = i.value();
       
   656 	delete iap;
       
   657 	i.remove();
       
   658     }
       
   659 
       
   660     if (!firstUpdate)
       
   661 	emit configurationUpdateComplete();
       
   662 
       
   663     if (firstUpdate)
       
   664         firstUpdate = false;
       
   665 }
       
   666 
       
   667 
       
   668 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
       
   669 {
       
   670     /* Here we just return [ANY] request to icd and let the icd decide which
       
   671      * IAP to connect.
       
   672      */
       
   673     QNetworkConfiguration item;
       
   674     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
       
   675         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
       
   676     return item;
       
   677 }
       
   678 
       
   679 
       
   680 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
       
   681 {
       
   682     QTimer::singleShot(0, this, SLOT(updateConfigurations()));
       
   683 }
       
   684 
       
   685 
       
   686 void QNetworkConfigurationManagerPrivate::cleanup()
       
   687 {
       
   688     iapMonitor()->cleanup();
       
   689 }
       
   690 
       
   691 
       
   692 void QNetworkConfigurationManagerPrivate::configChanged(QNetworkConfigurationPrivate *ptr, bool added)
       
   693 {
       
   694     if (added) {
       
   695 	if (ptr && ptr->state == QNetworkConfiguration::Active) {
       
   696 	    onlineConfigurations++;
       
   697 	    if (!firstUpdate && onlineConfigurations == 1)
       
   698 		emit onlineStateChanged(true);
       
   699 	}
       
   700     } else {
       
   701 	if (ptr && ptr->state == QNetworkConfiguration::Active) {
       
   702 	    onlineConfigurations--;
       
   703 	    if (!firstUpdate && onlineConfigurations == 0)
       
   704 		emit onlineStateChanged(false);
       
   705 	    if (onlineConfigurations < 0)
       
   706 		onlineConfigurations = 0;
       
   707 	}
       
   708     }
       
   709 }
       
   710 
       
   711 
       
   712 #include "qnetworkconfigmanager_maemo.moc"
       
   713 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
       
   714 
       
   715 QTM_END_NAMESPACE