qtmobility/src/bearer/qnetworkconfigmanager_maemo.cpp
branchRCL_3
changeset 2 5822d84012fb
parent 0 cfcbf08528c4
child 3 87be51aa5b5b
equal deleted inserted replaced
0:cfcbf08528c4 2:5822d84012fb
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the Qt Mobility Components.
     7 ** This file is part of the Qt Mobility Components.
     8 **
     8 **
   204 {
   204 {
   205     QString id = iap_id;
   205     QString id = iap_id;
   206     d->deleteConfiguration(id);
   206     d->deleteConfiguration(id);
   207 }
   207 }
   208 
   208 
   209 
       
   210 
       
   211 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
   209 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
   212 {
   210 {
   213     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
   211     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
   214     capFlags |= QNetworkConfigurationManager::DataStatistics;
   212     capFlags |= QNetworkConfigurationManager::DataStatistics;
   215     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
   213     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
   216 }
   214     capFlags |= QNetworkConfigurationManager::NetworkSessionRequired;
   217 
   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 }
   218 
   247 
   219 static inline QString network_attrs_to_security(uint network_attrs)
   248 static inline QString network_attrs_to_security(uint network_attrs)
   220 {
   249 {
   221     uint cap = 0;
   250     uint cap = 0;
   222     nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
   251     nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
   260 #endif
   289 #endif
   261 
   290 
   262 	    QNetworkConfiguration item;
   291 	    QNetworkConfiguration item;
   263 	    item.d = priv;
   292 	    item.d = priv;
   264 	    emit configurationRemoved(item);
   293 	    emit configurationRemoved(item);
   265 	    configChanged(priv.data(), false);
       
   266 	} else
   294 	} else
   267 	    qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
   295 	    qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
   268     } else {
   296     } else {
   269 #ifdef BEARER_MANAGEMENT_DEBUG
   297 #ifdef BEARER_MANAGEMENT_DEBUG
   270 	qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
   298 	qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
   272     }
   300     }
   273 }
   301 }
   274 
   302 
   275 
   303 
   276 uint32_t QNetworkConfigurationManagerPrivate::getNetworkAttrs(bool is_iap_id,
   304 uint32_t QNetworkConfigurationManagerPrivate::getNetworkAttrs(bool is_iap_id,
   277 							    QString& iap_id,
   305                                 const QString& iap_id,
   278 							    QString& iap_type,
   306 							    QString& iap_type,
   279 							    QString security_method)
   307 							    QString security_method)
   280 {
   308 {
   281     guint network_attr = 0;
   309     guint network_attr = 0;
   282     dbus_uint32_t cap = 0;
   310     dbus_uint32_t cap = 0;
   318 }
   346 }
   319 
   347 
   320 
   348 
   321 void QNetworkConfigurationManagerPrivate::addConfiguration(QString& iap_id)
   349 void QNetworkConfigurationManagerPrivate::addConfiguration(QString& iap_id)
   322 {
   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 
   323     if (!accessPointConfigurations.contains(iap_id)) {
   360     if (!accessPointConfigurations.contains(iap_id)) {
   324 	Maemo::IAPConf saved_iap(iap_id);
   361 	Maemo::IAPConf saved_iap(iap_id);
   325 	QString iap_type = saved_iap.value("type").toString();
   362         QString iap_type = saved_iap.value("type").toString();
   326 	if (!iap_type.isEmpty()) {
   363         QString iap_name = saved_iap.value("name").toString();
   327 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   364         QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
   328 	    cpPriv->name = saved_iap.value("name").toString();
   365         if (!iap_type.isEmpty() && !iap_name.isEmpty()) {
   329 	    if (cpPriv->name.isEmpty())
   366             // Check if new IAP is actually Undefined WLAN configuration
   330 		cpPriv->name = iap_id;
   367             // Note: SSID is used as an iap id for Undefined WLAN configurations
   331 	    cpPriv->isValid = true;
   368             //       => configuration must be searched using SSID
   332 	    cpPriv->id = iap_id;
   369             if (!ssid.isEmpty() && accessPointConfigurations.contains(ssid)) {
   333 	    cpPriv->iap_type = iap_type;
   370                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.take(ssid);
   334 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   371                 if (ptr.data()) {
   335 	    cpPriv->service_id = saved_iap.value("service_id").toString();
   372                     QString iap_type = saved_iap.value("type").toString();
   336 	    cpPriv->service_type = saved_iap.value("service_type").toString();
   373                     ptr->id = iap_id;
   337 	    if (iap_type.startsWith("WLAN")) {
   374                     ptr->iap_type = iap_type;
   338 		QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
   375                     ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   339 		if (ssid.isEmpty()) {
   376                     ptr->network_id = ssid;
   340 		    qWarning() << "Cannot get ssid for" << iap_id;
   377                     ptr->service_id = saved_iap.value("service_id").toString();
   341 		}
   378                     ptr->service_type = saved_iap.value("service_type").toString();
   342 	    }
   379                     if (m_onlineIapId == iap_id) {
   343 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   380                         ptr->state = QNetworkConfiguration::Active;
   344 	    cpPriv->state = QNetworkConfiguration::Defined;
   381                     } else {
   345 
   382                         ptr->state = QNetworkConfiguration::Defined;
   346 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   383                     }
   347 	    accessPointConfigurations.insert(iap_id, ptr);
   384                     accessPointConfigurations.insert(iap_id, ptr);
   348 
   385                     configurationChanged(ptr.data());
   349 #ifdef BEARER_MANAGEMENT_DEBUG
   386                 }
   350 	    qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
   387             } else {
   351 #endif
   388                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   352 
   389                 cpPriv->name = saved_iap.value("name").toString();
   353 	    QNetworkConfiguration item;
   390                 if (cpPriv->name.isEmpty())
   354 	    item.d = ptr;
   391                     cpPriv->name = iap_id;
   355 	    emit configurationAdded(item);
   392                 cpPriv->isValid = true;
   356 	    configChanged(ptr.data(), true);
   393                 cpPriv->id = iap_id;
   357 	} else {
   394                 cpPriv->iap_type = iap_type;
   358 	    qWarning("IAP %s does not have \"type\" field defined, skipping this IAP.", iap_id.toAscii().data());
   395                 cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   359 	}
   396                 cpPriv->service_id = saved_iap.value("service_id").toString();
       
   397                 cpPriv->service_type = saved_iap.value("service_type").toString();
       
   398                 if (iap_type.startsWith("WLAN")) {
       
   399                     QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
       
   400                     if (ssid.isEmpty()) {
       
   401                         qWarning() << "Cannot get ssid for" << iap_id;
       
   402                     }
       
   403                     cpPriv->network_id = ssid;
       
   404                 }
       
   405                 cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   406                 if (m_onlineIapId == iap_id) {
       
   407                     cpPriv->state = QNetworkConfiguration::Active;
       
   408                 } else {
       
   409                     cpPriv->state = QNetworkConfiguration::Defined;
       
   410                 }
       
   411                 cpPriv->manager = this;
       
   412 
       
   413                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   414                 accessPointConfigurations.insert(iap_id, ptr);
       
   415 
       
   416 #ifdef BEARER_MANAGEMENT_DEBUG
       
   417                 qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
       
   418 #endif
       
   419                 QNetworkConfiguration item;
       
   420                 item.d = ptr;
       
   421                 emit configurationAdded(item);
       
   422             }
       
   423         } else {
       
   424             qWarning("IAP %s does not have \"type\" or \"name\" fields defined, skipping this IAP.", iap_id.toAscii().data());
       
   425         }
   360     } else {
   426     } else {
   361 #ifdef BEARER_MANAGEMENT_DEBUG
   427 #ifdef BEARER_MANAGEMENT_DEBUG
   362 	qDebug() << "IAP" << iap_id << "already in db.";
   428 	qDebug() << "IAP" << iap_id << "already in db.";
   363 #endif
   429 #endif
   364 
   430 
   365 	/* Check if the data in db changed and update configuration accordingly
   431 	/* Check if the data in db changed and update configuration accordingly
   366 	 */
   432 	 */
   367 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.take(iap_id);
   433         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iap_id);
   368 	if (ptr.data()) {
   434 	if (ptr.data()) {
   369 	    Maemo::IAPConf changed_iap(iap_id);
   435 	    Maemo::IAPConf changed_iap(iap_id);
   370 	    QString iap_type = changed_iap.value("type").toString();
   436 	    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 */
   437 	    bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */
   372 
   438 
   381 		ptr->isValid = true;
   447 		ptr->isValid = true;
   382 		if (ptr->iap_type != iap_type) {
   448 		if (ptr->iap_type != iap_type) {
   383 		    ptr->iap_type = iap_type;
   449 		    ptr->iap_type = iap_type;
   384 		    update_needed = true;
   450 		    update_needed = true;
   385 		}
   451 		}
   386 		if (iap_type.startsWith("WLAN")) {
   452         if (iap_type.startsWith(QLatin1String("WLAN"))) {
   387 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
   453 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
   388 		    if (ssid.isEmpty()) {
   454 		    if (ssid.isEmpty()) {
   389 			qWarning() << "Cannot get ssid for" << iap_id;
   455 			qWarning() << "Cannot get ssid for" << iap_id;
   390 		    }
   456 		    }
   391 		    if (ptr->network_id != ssid) {
   457 		    if (ptr->network_id != ssid) {
   392 			ptr->network_id = ssid;
   458                         ptr->network_id = ssid;
   393 			update_needed = true;
   459                         update_needed = true;
   394 		    }
   460 		    }
   395 		}
   461 		}
   396 	    }
   462 	    }
   397 	    accessPointConfigurations.insert(iap_id, ptr);
       
   398 	    if (update_needed) {
   463 	    if (update_needed) {
   399 		ptr->type = QNetworkConfiguration::InternetAccessPoint;
   464                 ptr->type = QNetworkConfiguration::InternetAccessPoint;
   400 		if (ptr->state != QNetworkConfiguration::Defined) {
   465                 if (m_onlineIapId == iap_id) {
       
   466                     if (ptr->state < QNetworkConfiguration::Active) {
       
   467                         ptr->state = QNetworkConfiguration::Active;
       
   468                         configurationChanged(ptr.data());
       
   469                     }
       
   470                 } else if (ptr->state < QNetworkConfiguration::Defined) {
   401 		    ptr->state = QNetworkConfiguration::Defined;
   471 		    ptr->state = QNetworkConfiguration::Defined;
   402 		    configurationChanged(ptr.data());
   472                     configurationChanged(ptr.data());
   403 		}
   473                 }
   404 	    }
   474 	    }
   405 	} else {
   475 	} else {
   406 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
   476 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
   407 	}
   477 	}
   408     }
   478     }
   409 }
   479 }
   410 
   480 
   411 
       
   412 void QNetworkConfigurationManagerPrivate::updateConfigurations()
   481 void QNetworkConfigurationManagerPrivate::updateConfigurations()
   413 {
   482 {
   414     /* Contains known network id (like ssid) from storage */
   483     doUpdateConfigurations();
   415     QMultiHash<QByteArray, SSIDInfo* > knownConfigs;
   484 }
   416 
   485 
   417     /* All the scanned access points */
   486 void QNetworkConfigurationManagerPrivate::doUpdateConfigurations(QList<Maemo::IcdScanResult> scanned)
   418     QList<Maemo::IcdScanResult> scanned;
   487 {
   419 
   488     /* Contains all known iap_ids from storage */
   420     /* Turn on IAP monitoring */
   489     QList<QString> knownConfigs = accessPointConfigurations.keys();
   421     iapMonitor()->setup(this);
   490 
   422 
   491     /* Contains all known WLAN network ids (like ssid) from storage */
   423     if (firstUpdate) {
   492     QMultiHash<QByteArray, SSIDInfo* > notDiscoveredWLANConfigs;
   424 	/* We create a default configuration which is a pseudo config */
   493 
   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;
   494     QList<QString> all_iaps;
   442     Maemo::IAPConf::getAll(all_iaps);
   495     Maemo::IAPConf::getAll(all_iaps);
   443 
   496 
   444     foreach (QString iap_id, all_iaps) {
   497     foreach (const QString &iap_id, all_iaps) {
   445 	QByteArray ssid;
   498 	QByteArray ssid;
   446 
   499 
   447 	Maemo::IAPConf saved_ap(iap_id);
   500 	Maemo::IAPConf saved_ap(iap_id);
   448 	bool is_temporary = saved_ap.value("temporary").toBool();
   501 	bool is_temporary = saved_ap.value("temporary").toBool();
   449 	if (is_temporary) {
   502     if (is_temporary) {
   450 #ifdef BEARER_MANAGEMENT_DEBUG
   503 #ifdef BEARER_MANAGEMENT_DEBUG
   451 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
   504 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
   452 #endif
   505 #endif
   453 	    continue;
   506 	    continue;
   454 	}
   507 	}
   455 
   508 
   456 	QString iap_type = saved_ap.value("type").toString();
   509 	QString iap_type = saved_ap.value("type").toString();
   457 	if (iap_type.startsWith("WLAN")) {
   510     if (iap_type.startsWith(QLatin1String("WLAN"))) {
   458 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
   511 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
   459 	    if (ssid.isEmpty()) {
   512 	    if (ssid.isEmpty()) {
   460 		qWarning() << "Cannot get ssid for" << iap_id;
   513 		qWarning() << "Cannot get ssid for" << iap_id;
   461 		continue;
   514 		continue;
   462 	    }
   515 	    }
   463 
   516 
   464 	    QString security_method = saved_ap.value("wlan_security").toString();
   517 	    QString security_method = saved_ap.value("wlan_security").toString();
   465 	    SSIDInfo *info = new SSIDInfo;
   518 	    SSIDInfo *info = new SSIDInfo;
   466 	    info->iap_id = iap_id;
   519 	    info->iap_id = iap_id;
   467 	    info->wlan_security = security_method;
   520 	    info->wlan_security = security_method;
   468 	    knownConfigs.insert(ssid, info);
   521             notDiscoveredWLANConfigs.insert(ssid, info);
   469 	} else if (iap_type.isEmpty()) {
   522 	} else if (iap_type.isEmpty()) {
   470 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
   523 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
   471 	    continue;
   524 	    continue;
   472 	} else {
   525 	} else {
   473 #ifdef BEARER_MANAGEMENT_DEBUG
   526 #ifdef BEARER_MANAGEMENT_DEBUG
   483 		if (!ssid.isEmpty() && ssid.size() > 0)
   536 		if (!ssid.isEmpty() && ssid.size() > 0)
   484 		    cpPriv->name = ssid.data();
   537 		    cpPriv->name = ssid.data();
   485 		else
   538 		else
   486 		    cpPriv->name = iap_id;
   539 		    cpPriv->name = iap_id;
   487 	    }
   540 	    }
   488 	    cpPriv->isValid = true;
   541             cpPriv->isValid = true;
   489 	    cpPriv->id = iap_id;
   542 	    cpPriv->id = iap_id;
   490 	    cpPriv->network_id = ssid;
   543 	    cpPriv->network_id = ssid;
   491 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   544 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   492 	    cpPriv->iap_type = iap_type;
   545 	    cpPriv->iap_type = iap_type;
   493 	    cpPriv->service_id = saved_ap.value("service_id").toString();
   546 	    cpPriv->service_id = saved_ap.value("service_id").toString();
   501 
   554 
   502 #ifdef BEARER_MANAGEMENT_DEBUG
   555 #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() : "-");
   556 	    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
   557 #endif
   505 	} else {
   558 	} else {
       
   559             knownConfigs.removeOne(iap_id);
   506 #ifdef BEARER_MANAGEMENT_DEBUG
   560 #ifdef BEARER_MANAGEMENT_DEBUG
   507 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
   561 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
   508 #endif
   562 #endif
   509 	}
   563 	}
   510     }
   564     }
   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 
   565 
   535     /* This is skipped in the first update as scanned size is zero */
   566     /* This is skipped in the first update as scanned size is zero */
   536     if (!scanned.isEmpty())
   567     if (!scanned.isEmpty())
   537       for (int i=0; i<scanned.size(); ++i) {
   568       for (int i=0; i<scanned.size(); ++i) {
   538 	const Maemo::IcdScanResult ap = scanned.at(i); 
   569 	const Maemo::IcdScanResult ap = scanned.at(i); 
   539 
   570 
   540 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
   571 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
   541 	    /* The network_id is IAP id, so the IAP is a known one */
   572 	    /* The network_id is IAP id, so the IAP is a known one */
   542 	    QString iapid = ap.scan.network_id.data();
   573 	    QString iapid = ap.scan.network_id.data();
   543 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iapid);
   574             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iapid);
   544 	    if (priv.data()) {
   575 	    if (priv.data()) {
   545 		priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */
   576                 bool stateChanged = false;
       
   577                 // Check if state is not already Discovered or Active
       
   578                 if (priv->state < QNetworkConfiguration::Discovered) {
       
   579                     priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */
       
   580                     stateChanged = true;
       
   581                 }
   546 		priv->network_attrs = ap.scan.network_attrs;
   582 		priv->network_attrs = ap.scan.network_attrs;
   547 		priv->service_id = ap.scan.service_id;
   583 		priv->service_id = ap.scan.service_id;
   548 		priv->service_type = ap.scan.service_type;
   584 		priv->service_type = ap.scan.service_type;
   549 		priv->service_attrs = ap.scan.service_attrs;
   585 		priv->service_attrs = ap.scan.service_attrs;
   550 
   586 
   551 		configurationChanged(priv.data());
   587                 if (stateChanged) {
   552 		accessPointConfigurations.insert(iapid, priv);
   588                     configurationChanged(priv.data());
       
   589                 }
   553 #ifdef BEARER_MANAGEMENT_DEBUG
   590 #ifdef BEARER_MANAGEMENT_DEBUG
   554 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
   591 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
   555 #endif
   592 #endif
   556 
   593 
   557 		if (!ap.scan.network_type.startsWith("WLAN"))
   594         if (!ap.scan.network_type.startsWith(QLatin1String("WLAN")))
   558 		    continue; // not a wlan AP
   595 		    continue; // not a wlan AP
   559 
   596 
   560 		/* Remove scanned AP from known configurations so that we can
   597                 /* Remove scanned AP from discovered WLAN configurations so that we can
   561 		 * emit configurationRemoved signal later
   598 		 * emit configurationRemoved signal later
   562 		 */
   599 		 */
   563 		QList<SSIDInfo* > known_iaps = knownConfigs.values(priv->network_id);
   600                 QList<SSIDInfo* > known_iaps = notDiscoveredWLANConfigs.values(priv->network_id);
   564 	    rescan_list:
   601 	    rescan_list:
   565 		if (!known_iaps.isEmpty()) {
   602 		if (!known_iaps.isEmpty()) {
   566 		    for (int k=0; k<known_iaps.size(); ++k) {
   603 		    for (int k=0; k<known_iaps.size(); ++k) {
   567 			SSIDInfo *iap = known_iaps.at(k);
   604 			SSIDInfo *iap = known_iaps.at(k);
   568 
   605 
   571 #endif
   608 #endif
   572 
   609 
   573 			if (iap->wlan_security == 
   610 			if (iap->wlan_security == 
   574 			    network_attrs_to_security(ap.scan.network_attrs)) {
   611 			    network_attrs_to_security(ap.scan.network_attrs)) {
   575 			    /* Remove IAP from the list */
   612 			    /* Remove IAP from the list */
   576 			    knownConfigs.remove(priv->network_id, iap);
   613                             notDiscoveredWLANConfigs.remove(priv->network_id, iap);
   577 #ifdef BEARER_MANAGEMENT_DEBUG
   614 #ifdef BEARER_MANAGEMENT_DEBUG
   578 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
   615 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
   579 #endif
   616 #endif
   580 			    known_iaps.removeAt(k);
   617 			    known_iaps.removeAt(k);
   581 			    delete iap;
   618 			    delete iap;
   586 	    } else {
   623 	    } else {
   587 		qWarning() << "IAP" << iapid << "is missing in configuration.";
   624 		qWarning() << "IAP" << iapid << "is missing in configuration.";
   588 	    }
   625 	    }
   589 
   626 
   590 	} else {
   627 	} else {
   591 	    /* Non saved access point data */
   628             /* Non saved access point data */
   592 	    QByteArray scanned_ssid = ap.scan.network_id;
   629 	    QByteArray scanned_ssid = ap.scan.network_id;
   593 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   630             if (!accessPointConfigurations.contains(scanned_ssid)) {
   594 	    QString hrs = scanned_ssid.data();
   631                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   595 
   632                 QString hrs = scanned_ssid.data();
   596 	    cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
   633 
   597 	    cpPriv->isValid = true;
   634                 cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
   598 	    cpPriv->id = scanned_ssid.data();  // Note: id is now ssid, it should be set to IAP id if the IAP is saved
   635                 cpPriv->isValid = true;
   599 	    cpPriv->network_id = scanned_ssid;
   636                 cpPriv->id = scanned_ssid.data();  // Note: id is now ssid, it should be set to IAP id if the IAP is saved
   600 	    cpPriv->iap_type = ap.scan.network_type;
   637                 cpPriv->network_id = scanned_ssid;
   601 	    cpPriv->network_attrs = ap.scan.network_attrs;
   638                 cpPriv->iap_type = ap.scan.network_type;
   602 	    cpPriv->service_id = ap.scan.service_id;
   639                 cpPriv->network_attrs = ap.scan.network_attrs;
   603 	    cpPriv->service_type = ap.scan.service_type;
   640                 cpPriv->service_id = ap.scan.service_id;
   604 	    cpPriv->service_attrs = ap.scan.service_attrs;
   641                 cpPriv->service_type = ap.scan.service_type;
   605 	    cpPriv->manager = this;
   642                 cpPriv->service_attrs = ap.scan.service_attrs;
   606 
   643                 cpPriv->manager = this;
   607 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   644 
   608 	    cpPriv->state = QNetworkConfiguration::Undefined;
   645                 cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   609 
   646                 cpPriv->state = QNetworkConfiguration::Undefined;
   610 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   647 
   611 	    accessPointConfigurations.insert(cpPriv->id, ptr);
   648                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   612 
   649                 accessPointConfigurations.insert(cpPriv->id, ptr);
   613 #ifdef BEARER_MANAGEMENT_DEBUG
   650 
   614 	    qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
   651     #ifdef BEARER_MANAGEMENT_DEBUG
   615 #endif
   652                 qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
   616 
   653     #endif
   617 	    QNetworkConfiguration item;
   654 
   618 	    item.d = ptr;
   655                 QNetworkConfiguration item;
   619 	    emit configurationAdded(item);
   656                 item.d = ptr;
   620 	}
   657                 emit configurationAdded(item);
   621       }
   658             } else {
   622 
   659                 knownConfigs.removeOne(scanned_ssid);
   623 
   660             }
   624     /* Remove non existing iaps since last update */
   661         }
       
   662     }
       
   663 
   625     if (!firstUpdate) {
   664     if (!firstUpdate) {
   626 	QHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
   665         // Update Defined status to all defined WLAN IAPs which
       
   666         // could not be found when access points were scanned
       
   667         QHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
   627 	while (i.hasNext()) {
   668 	while (i.hasNext()) {
   628 	    i.next();
   669 	    i.next();
   629 	    SSIDInfo *iap = i.value();
   670 	    SSIDInfo *iap = i.value();
   630 	    QString iap_id = iap->iap_id;
   671 	    QString iap_id = iap->iap_id;
   631 	    //qDebug() << i.key() << ": " << iap_id;
   672 	    //qDebug() << i.key() << ": " << iap_id;
   632 
   673 
   633 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iap_id);
   674             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iap_id);
   634 	    if (priv.data()) {
   675 	    if (priv.data()) {
   635 		priv->isValid = false;
   676                 // WLAN AccessPoint configuration could not be Discovered
   636 #ifdef BEARER_MANAGEMENT_DEBUG
   677                 // => Make sure that configuration state is Defined
   637 		qDebug() << "IAP" << iap_id << "was removed as it was not found in scan.";
   678                 if (priv->state > QNetworkConfiguration::Defined) {
   638 #endif
   679                     priv->state = QNetworkConfiguration::Defined;
   639 
   680                     configurationChanged(priv.data());
   640 		QNetworkConfiguration item;
   681                 }
   641 		item.d = priv;
   682 	    }
   642 		emit configurationRemoved(item);
   683 	}
   643 		configChanged(priv.data(), false);
   684 
   644 
   685         /* Remove non existing iaps since last update */
       
   686         foreach (QString oldIface, knownConfigs) {
       
   687             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
       
   688             if (priv.data()) {
       
   689                 priv->isValid = false;
       
   690                 QNetworkConfiguration item;
       
   691                 item.d = priv;
       
   692                 emit configurationRemoved(item);
   645 		//if we would have SNAP support we would have to remove the references
   693 		//if we would have SNAP support we would have to remove the references
   646 		//from existing ServiceNetworks to the removed access point configuration
   694 		//from existing ServiceNetworks to the removed access point configuration
   647 	    }
   695             }
   648 	}
   696         }
   649     }
   697     }
   650 
   698 
   651 
   699     QMutableHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
   652     QMutableHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
       
   653     while (i.hasNext()) {
   700     while (i.hasNext()) {
   654 	i.next();
   701 	i.next();
   655 	SSIDInfo *iap = i.value();
   702 	SSIDInfo *iap = i.value();
   656 	delete iap;
   703 	delete iap;
   657 	i.remove();
   704 	i.remove();
   661 	emit configurationUpdateComplete();
   708 	emit configurationUpdateComplete();
   662 
   709 
   663     if (firstUpdate)
   710     if (firstUpdate)
   664         firstUpdate = false;
   711         firstUpdate = false;
   665 }
   712 }
   666 
       
   667 
   713 
   668 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
   714 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
   669 {
   715 {
   670     /* Here we just return [ANY] request to icd and let the icd decide which
   716     /* Here we just return [ANY] request to icd and let the icd decide which
   671      * IAP to connect.
   717      * IAP to connect.
   674     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
   720     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
   675         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
   721         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
   676     return item;
   722     return item;
   677 }
   723 }
   678 
   724 
       
   725 void QNetworkConfigurationManagerPrivate::startListeningStateSignalsForAllConnections()
       
   726 {
       
   727     // Start listening ICD_DBUS_API_STATE_SIG signals
       
   728     m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
       
   729                                           ICD_DBUS_API_PATH,
       
   730                                           ICD_DBUS_API_INTERFACE,
       
   731                                           ICD_DBUS_API_STATE_SIG,
       
   732                                           this, SLOT(connectionStateSignalsSlot(QDBusMessage)));
       
   733 
       
   734     // Calling ICD_DBUS_API_STATE_REQ makes sure that initial state will be updated immediately
       
   735     m_gettingInitialConnectionState = true;
       
   736     m_dbusInterface->call(ICD_DBUS_API_STATE_REQ);
       
   737 }
       
   738 
       
   739 void QNetworkConfigurationManagerPrivate::connectionStateSignalsSlot(QDBusMessage msg)
       
   740 {
       
   741     QList<QVariant> arguments = msg.arguments();
       
   742     if (arguments[1].toUInt() != 0 || arguments.count() < 8) {
       
   743         return;
       
   744     }
       
   745 
       
   746     QString iapid = arguments[5].toByteArray().data();
       
   747     uint icd_connection_state = arguments[7].toUInt();
       
   748 
       
   749     switch (icd_connection_state) {
       
   750     case ICD_STATE_CONNECTED:
       
   751         {
       
   752         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iapid);
       
   753         if (ptr.data()) {
       
   754             ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   755             if (ptr->state != QNetworkConfiguration::Active) {
       
   756                 ptr->state = QNetworkConfiguration::Active;
       
   757                 if (!m_gettingInitialConnectionState) {
       
   758                     configurationChanged(ptr.data());
       
   759                     if (m_onlineIapId.isEmpty()) {
       
   760                         emit onlineStateChanged(true);
       
   761                     }
       
   762                 }
       
   763                 m_onlineIapId = iapid;
       
   764             }
       
   765         } else {
       
   766             // This gets called when new WLAN IAP is created using Connection dialog
       
   767             // At this point Undefined WLAN configuration has SSID as iap id
       
   768             // => Because of that configuration can not be found from
       
   769             //    accessPointConfigurations using correct iap id
       
   770             emit onlineStateChanged(true);
       
   771             m_onlineIapId = iapid;
       
   772         }
       
   773         break;
       
   774         }
       
   775     case ICD_STATE_DISCONNECTED:
       
   776         {
       
   777         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iapid);
       
   778         if (ptr.data()) {
       
   779             ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   780             if (ptr->state == QNetworkConfiguration::Active) {
       
   781                 ptr->state = QNetworkConfiguration::Discovered;
       
   782                 if (!m_gettingInitialConnectionState) {
       
   783                     configurationChanged(ptr.data());
       
   784 
       
   785                     // Note: If ICD switches used IAP from one to another:
       
   786                     //       1) new IAP is reported to be online first
       
   787                     //       2) old IAP is reported to be offline then
       
   788                     // => Device can be reported to be offline only
       
   789                     //    if last known online IAP is reported to be disconnected
       
   790                     if (iapid == m_onlineIapId) {
       
   791                         // It's known that there is only one global ICD connection
       
   792                         // => Because ICD state was reported to be DISCONNECTED, Device is offline
       
   793                         m_onlineIapId = QString();
       
   794                         emit onlineStateChanged(false);
       
   795                     }
       
   796                 }
       
   797             }
       
   798         } else {
       
   799             // Disconnected IAP was not found from accessPointConfigurations
       
   800             // => Reason: Online IAP was removed which resulted ICD to disconnect
       
   801             if (iapid == m_onlineIapId) {
       
   802                 // It's known that there is only one global ICD connection
       
   803                 // => Because ICD state was reported to be DISCONNECTED, Device is offline
       
   804                 m_onlineIapId = QString();
       
   805                 emit onlineStateChanged(false);
       
   806             }
       
   807         }
       
   808         break;
       
   809         }
       
   810     default:
       
   811         break;
       
   812     }
       
   813     
       
   814     emit iapStateChanged(iapid, icd_connection_state);
       
   815 
       
   816     m_gettingInitialConnectionState = false;
       
   817 }
   679 
   818 
   680 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   819 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   681 {
   820 {
   682     QTimer::singleShot(0, this, SLOT(updateConfigurations()));
   821     if (m_scanGoingOn) {
   683 }
   822         return;
   684 
   823     }
       
   824     m_scanGoingOn = true;
       
   825 
       
   826     m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
       
   827                                           ICD_DBUS_API_PATH,
       
   828                                           ICD_DBUS_API_INTERFACE,
       
   829                                           ICD_DBUS_API_SCAN_SIG,
       
   830                                           this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage)));
       
   831 
       
   832     QDBusMessage msg = m_dbusInterface->call(ICD_DBUS_API_SCAN_REQ,
       
   833                                              (uint)ICD_SCAN_REQUEST_ACTIVE);
       
   834     m_typesToBeScanned = msg.arguments()[0].value<QStringList>();
       
   835     m_scanTimer.start(ICD_SHORT_SCAN_TIMEOUT);
       
   836 }
       
   837 
       
   838 void QNetworkConfigurationManagerPrivate::cancelAsyncConfigurationUpdate()
       
   839 {
       
   840     if (!m_scanGoingOn) {
       
   841         return;
       
   842     }
       
   843     m_scanGoingOn = false;
       
   844 
       
   845     if (m_scanTimer.isActive()) {
       
   846         m_scanTimer.stop();
       
   847     }
       
   848 
       
   849     m_dbusInterface->connection().disconnect(ICD_DBUS_API_INTERFACE,
       
   850                                              ICD_DBUS_API_PATH,
       
   851                                              ICD_DBUS_API_INTERFACE,
       
   852                                              ICD_DBUS_API_SCAN_SIG,
       
   853                                              this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage)));
       
   854 
       
   855     // Stop scanning rounds by calling ICD_DBUS_API_SCAN_CANCEL
       
   856     // <=> If ICD_DBUS_API_SCAN_CANCEL is not called, new scanning round will
       
   857     //     be started after the module scan timeout.
       
   858     m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
       
   859 }
       
   860 
       
   861 void QNetworkConfigurationManagerPrivate::finishAsyncConfigurationUpdate()
       
   862 {
       
   863     cancelAsyncConfigurationUpdate();
       
   864     doUpdateConfigurations(m_scanResult);
       
   865     m_scanResult.clear();
       
   866 }
       
   867 
       
   868 void QNetworkConfigurationManagerPrivate::asyncUpdateConfigurationsSlot(QDBusMessage msg)
       
   869 {
       
   870     QList<QVariant> arguments = msg.arguments();
       
   871     uint icd_scan_status = arguments.takeFirst().toUInt();
       
   872     if (icd_scan_status == ICD_SCAN_COMPLETE) {
       
   873         m_typesToBeScanned.removeOne(arguments[6].toString());
       
   874         if (!m_typesToBeScanned.count()) {
       
   875             finishAsyncConfigurationUpdate();
       
   876         }
       
   877     } else {
       
   878         Maemo::IcdScanResult scanResult;
       
   879         scanResult.status = icd_scan_status;
       
   880         scanResult.timestamp = arguments.takeFirst().toUInt();
       
   881         scanResult.scan.service_type = arguments.takeFirst().toString();
       
   882         scanResult.service_name = arguments.takeFirst().toString();
       
   883         scanResult.scan.service_attrs = arguments.takeFirst().toUInt();
       
   884         scanResult.scan.service_id = arguments.takeFirst().toString();
       
   885         scanResult.service_priority = arguments.takeFirst().toInt();
       
   886         scanResult.scan.network_type = arguments.takeFirst().toString();
       
   887         scanResult.network_name = arguments.takeFirst().toString();
       
   888         scanResult.scan.network_attrs = arguments.takeFirst().toUInt();
       
   889         scanResult.scan.network_id = arguments.takeFirst().toByteArray();
       
   890         scanResult.network_priority = arguments.takeFirst().toInt();
       
   891         scanResult.signal_strength = arguments.takeFirst().toInt();
       
   892         scanResult.station_id = arguments.takeFirst().toString();
       
   893         scanResult.signal_dB = arguments.takeFirst().toInt();
       
   894 
       
   895         m_scanResult.append(scanResult);
       
   896     }
       
   897 }
   685 
   898 
   686 void QNetworkConfigurationManagerPrivate::cleanup()
   899 void QNetworkConfigurationManagerPrivate::cleanup()
   687 {
   900 {
       
   901     if (m_scanGoingOn) {
       
   902         m_scanTimer.stop();
       
   903         m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
       
   904     }
   688     iapMonitor()->cleanup();
   905     iapMonitor()->cleanup();
   689 }
   906 }
   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 
   907 
   712 #include "qnetworkconfigmanager_maemo.moc"
   908 #include "qnetworkconfigmanager_maemo.moc"
   713 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
   909 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
   714 
   910 
   715 QTM_END_NAMESPACE
   911 QTM_END_NAMESPACE