qtmobility/src/bearer/qnetworkconfigmanager_maemo.cpp
changeset 4 90517678cc4f
parent 0 cfcbf08528c4
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
     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                                                               const 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;
   283 
   311 
   284     if (iap_type == "WLAN_INFRA")
   312     if (iap_type == "WLAN_INFRA")
   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                     ptr->id = iap_id;
   336 	    cpPriv->service_type = saved_iap.value("service_type").toString();
   373                     ptr->iap_type = iap_type;
   337 	    if (iap_type.startsWith("WLAN")) {
   374                     ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   338 		QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
   375                     ptr->network_id = ssid;
   339 		if (ssid.isEmpty()) {
   376                     ptr->service_id = saved_iap.value("service_id").toString();
   340 		    qWarning() << "Cannot get ssid for" << iap_id;
   377                     ptr->service_type = saved_iap.value("service_type").toString();
   341 		}
   378                     if (m_onlineIapId == iap_id) {
   342 	    }
   379                         ptr->state = QNetworkConfiguration::Active;
   343 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   380                     } else {
   344 	    cpPriv->state = QNetworkConfiguration::Defined;
   381                         ptr->state = QNetworkConfiguration::Defined;
   345 
   382                     }
   346 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   383                     accessPointConfigurations.insert(iap_id, ptr);
   347 	    accessPointConfigurations.insert(iap_id, ptr);
   384                     configurationChanged(ptr.data());
   348 
   385                 }
   349 #ifdef BEARER_MANAGEMENT_DEBUG
   386             } else {
   350 	    qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
   387                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   351 #endif
   388                 cpPriv->name = saved_iap.value("name").toString();
   352 
   389                 if (cpPriv->name.isEmpty())
   353 	    QNetworkConfiguration item;
   390                     cpPriv->name = iap_id;
   354 	    item.d = ptr;
   391                 cpPriv->isValid = true;
   355 	    emit configurationAdded(item);
   392                 cpPriv->id = iap_id;
   356 	    configChanged(ptr.data(), true);
   393                 cpPriv->iap_type = iap_type;
   357 	} else {
   394                 cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   358 	    qWarning("IAP %s does not have \"type\" field defined, skipping this IAP.", iap_id.toAscii().data());
   395                 cpPriv->service_id = saved_iap.value("service_id").toString();
   359 	}
   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         }
   360     } else {
   425     } else {
   361 #ifdef BEARER_MANAGEMENT_DEBUG
   426 #ifdef BEARER_MANAGEMENT_DEBUG
   362 	qDebug() << "IAP" << iap_id << "already in db.";
   427 	qDebug() << "IAP" << iap_id << "already in db.";
   363 #endif
   428 #endif
   364 
   429 
   365 	/* Check if the data in db changed and update configuration accordingly
   430 	/* Check if the data in db changed and update configuration accordingly
   366 	 */
   431 	 */
   367 	QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.take(iap_id);
   432         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = accessPointConfigurations.value(iap_id);
   368 	if (ptr.data()) {
   433 	if (ptr.data()) {
   369 	    Maemo::IAPConf changed_iap(iap_id);
   434 	    Maemo::IAPConf changed_iap(iap_id);
   370 	    QString iap_type = changed_iap.value("type").toString();
   435 	    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 */
   436 	    bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */
   372 
   437 
   381 		ptr->isValid = true;
   446 		ptr->isValid = true;
   382 		if (ptr->iap_type != iap_type) {
   447 		if (ptr->iap_type != iap_type) {
   383 		    ptr->iap_type = iap_type;
   448 		    ptr->iap_type = iap_type;
   384 		    update_needed = true;
   449 		    update_needed = true;
   385 		}
   450 		}
   386 		if (iap_type.startsWith("WLAN")) {
   451         if (iap_type.startsWith(QLatin1String("WLAN"))) {
   387 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
   452 		    QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
   388 		    if (ssid.isEmpty()) {
   453 		    if (ssid.isEmpty()) {
   389 			qWarning() << "Cannot get ssid for" << iap_id;
   454 			qWarning() << "Cannot get ssid for" << iap_id;
   390 		    }
   455 		    }
   391 		    if (ptr->network_id != ssid) {
   456 		    if (ptr->network_id != ssid) {
   392 			ptr->network_id = ssid;
   457                         ptr->network_id = ssid;
   393 			update_needed = true;
   458                         update_needed = true;
   394 		    }
   459 		    }
   395 		}
   460 		}
   396 	    }
   461 	    }
   397 	    accessPointConfigurations.insert(iap_id, ptr);
       
   398 	    if (update_needed) {
   462 	    if (update_needed) {
   399 		ptr->type = QNetworkConfiguration::InternetAccessPoint;
   463                 ptr->type = QNetworkConfiguration::InternetAccessPoint;
   400 		if (ptr->state != QNetworkConfiguration::Defined) {
   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) {
   401 		    ptr->state = QNetworkConfiguration::Defined;
   470 		    ptr->state = QNetworkConfiguration::Defined;
   402 		    configurationChanged(ptr.data());
   471                     configurationChanged(ptr.data());
   403 		}
   472                 }
   404 	    }
   473 	    }
   405 	} else {
   474 	} else {
   406 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
   475 	    qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
   407 	}
   476 	}
   408     }
   477     }
   409 }
   478 }
   410 
   479 
   411 
       
   412 void QNetworkConfigurationManagerPrivate::updateConfigurations()
   480 void QNetworkConfigurationManagerPrivate::updateConfigurations()
   413 {
   481 {
   414     /* Contains known network id (like ssid) from storage */
   482     doUpdateConfigurations();
   415     QMultiHash<QByteArray, SSIDInfo* > knownConfigs;
   483 }
   416 
   484 
   417     /* All the scanned access points */
   485 void QNetworkConfigurationManagerPrivate::doUpdateConfigurations(QList<Maemo::IcdScanResult> scanned)
   418     QList<Maemo::IcdScanResult> scanned;
   486 {
   419 
   487     /* Contains all known iap_ids from storage */
   420     /* Turn on IAP monitoring */
   488     QList<QString> knownConfigs = accessPointConfigurations.keys();
   421     iapMonitor()->setup(this);
   489 
   422 
   490     /* Contains all known WLAN network ids (like ssid) from storage */
   423     if (firstUpdate) {
   491     QMultiHash<QByteArray, SSIDInfo* > notDiscoveredWLANConfigs;
   424 	/* We create a default configuration which is a pseudo config */
   492 
   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;
   493     QList<QString> all_iaps;
   442     Maemo::IAPConf::getAll(all_iaps);
   494     Maemo::IAPConf::getAll(all_iaps);
   443 
   495 
   444     foreach (QString iap_id, all_iaps) {
   496     foreach (const QString &iap_id, all_iaps) {
   445 	QByteArray ssid;
   497 	QByteArray ssid;
   446 
   498 
   447 	Maemo::IAPConf saved_ap(iap_id);
   499 	Maemo::IAPConf saved_ap(iap_id);
   448 	bool is_temporary = saved_ap.value("temporary").toBool();
   500 	bool is_temporary = saved_ap.value("temporary").toBool();
   449 	if (is_temporary) {
   501     if (is_temporary) {
   450 #ifdef BEARER_MANAGEMENT_DEBUG
   502 #ifdef BEARER_MANAGEMENT_DEBUG
   451 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
   503 	    qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
   452 #endif
   504 #endif
   453 	    continue;
   505 	    continue;
   454 	}
   506 	}
   455 
   507 
   456 	QString iap_type = saved_ap.value("type").toString();
   508 	QString iap_type = saved_ap.value("type").toString();
   457 	if (iap_type.startsWith("WLAN")) {
   509     if (iap_type.startsWith(QLatin1String("WLAN"))) {
   458 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
   510 	    ssid = saved_ap.value("wlan_ssid").toByteArray();
   459 	    if (ssid.isEmpty()) {
   511 	    if (ssid.isEmpty()) {
   460 		qWarning() << "Cannot get ssid for" << iap_id;
   512 		qWarning() << "Cannot get ssid for" << iap_id;
   461 		continue;
   513 		continue;
   462 	    }
   514 	    }
   463 
   515 
   464 	    QString security_method = saved_ap.value("wlan_security").toString();
   516 	    QString security_method = saved_ap.value("wlan_security").toString();
   465 	    SSIDInfo *info = new SSIDInfo;
   517 	    SSIDInfo *info = new SSIDInfo;
   466 	    info->iap_id = iap_id;
   518 	    info->iap_id = iap_id;
   467 	    info->wlan_security = security_method;
   519 	    info->wlan_security = security_method;
   468 	    knownConfigs.insert(ssid, info);
   520             notDiscoveredWLANConfigs.insert(ssid, info);
   469 	} else if (iap_type.isEmpty()) {
   521 	} else if (iap_type.isEmpty()) {
   470 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
   522 	    qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
   471 	    continue;
   523 	    continue;
   472 	} else {
   524 	} else {
   473 #ifdef BEARER_MANAGEMENT_DEBUG
   525 #ifdef BEARER_MANAGEMENT_DEBUG
   483 		if (!ssid.isEmpty() && ssid.size() > 0)
   535 		if (!ssid.isEmpty() && ssid.size() > 0)
   484 		    cpPriv->name = ssid.data();
   536 		    cpPriv->name = ssid.data();
   485 		else
   537 		else
   486 		    cpPriv->name = iap_id;
   538 		    cpPriv->name = iap_id;
   487 	    }
   539 	    }
   488 	    cpPriv->isValid = true;
   540             cpPriv->isValid = true;
   489 	    cpPriv->id = iap_id;
   541 	    cpPriv->id = iap_id;
   490 	    cpPriv->network_id = ssid;
   542 	    cpPriv->network_id = ssid;
   491 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   543 	    cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
   492 	    cpPriv->iap_type = iap_type;
   544 	    cpPriv->iap_type = iap_type;
   493 	    cpPriv->service_id = saved_ap.value("service_id").toString();
   545 	    cpPriv->service_id = saved_ap.value("service_id").toString();
   501 
   553 
   502 #ifdef BEARER_MANAGEMENT_DEBUG
   554 #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() : "-");
   555 	    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
   556 #endif
   505 	} else {
   557 	} else {
       
   558             knownConfigs.removeOne(iap_id);
   506 #ifdef BEARER_MANAGEMENT_DEBUG
   559 #ifdef BEARER_MANAGEMENT_DEBUG
   507 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
   560 	    qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
   508 #endif
   561 #endif
   509 	}
   562 	}
   510     }
   563     }
   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 
   564 
   535     /* This is skipped in the first update as scanned size is zero */
   565     /* This is skipped in the first update as scanned size is zero */
   536     if (!scanned.isEmpty())
   566     if (!scanned.isEmpty())
   537       for (int i=0; i<scanned.size(); ++i) {
   567       for (int i=0; i<scanned.size(); ++i) {
   538 	const Maemo::IcdScanResult ap = scanned.at(i); 
   568 	const Maemo::IcdScanResult ap = scanned.at(i); 
   539 
   569 
   540 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
   570 	if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
   541 	    /* The network_id is IAP id, so the IAP is a known one */
   571 	    /* The network_id is IAP id, so the IAP is a known one */
   542 	    QString iapid = ap.scan.network_id.data();
   572 	    QString iapid = ap.scan.network_id.data();
   543 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iapid);
   573             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iapid);
   544 	    if (priv.data()) {
   574 	    if (priv.data()) {
   545 		priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */
   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                 }
   546 		priv->network_attrs = ap.scan.network_attrs;
   581 		priv->network_attrs = ap.scan.network_attrs;
   547 		priv->service_id = ap.scan.service_id;
   582 		priv->service_id = ap.scan.service_id;
   548 		priv->service_type = ap.scan.service_type;
   583 		priv->service_type = ap.scan.service_type;
   549 		priv->service_attrs = ap.scan.service_attrs;
   584 		priv->service_attrs = ap.scan.service_attrs;
   550 
   585 
   551 		configurationChanged(priv.data());
   586                 if (stateChanged) {
   552 		accessPointConfigurations.insert(iapid, priv);
   587                     configurationChanged(priv.data());
       
   588                 }
   553 #ifdef BEARER_MANAGEMENT_DEBUG
   589 #ifdef BEARER_MANAGEMENT_DEBUG
   554 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
   590 		qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data());
   555 #endif
   591 #endif
   556 
   592 
   557 		if (!ap.scan.network_type.startsWith("WLAN"))
   593         if (!ap.scan.network_type.startsWith(QLatin1String("WLAN")))
   558 		    continue; // not a wlan AP
   594 		    continue; // not a wlan AP
   559 
   595 
   560 		/* Remove scanned AP from known configurations so that we can
   596                 /* Remove scanned AP from discovered WLAN configurations so that we can
   561 		 * emit configurationRemoved signal later
   597 		 * emit configurationRemoved signal later
   562 		 */
   598 		 */
   563 		QList<SSIDInfo* > known_iaps = knownConfigs.values(priv->network_id);
   599                 QList<SSIDInfo* > known_iaps = notDiscoveredWLANConfigs.values(priv->network_id);
   564 	    rescan_list:
   600 	    rescan_list:
   565 		if (!known_iaps.isEmpty()) {
   601 		if (!known_iaps.isEmpty()) {
   566 		    for (int k=0; k<known_iaps.size(); ++k) {
   602 		    for (int k=0; k<known_iaps.size(); ++k) {
   567 			SSIDInfo *iap = known_iaps.at(k);
   603 			SSIDInfo *iap = known_iaps.at(k);
   568 
   604 
   571 #endif
   607 #endif
   572 
   608 
   573 			if (iap->wlan_security == 
   609 			if (iap->wlan_security == 
   574 			    network_attrs_to_security(ap.scan.network_attrs)) {
   610 			    network_attrs_to_security(ap.scan.network_attrs)) {
   575 			    /* Remove IAP from the list */
   611 			    /* Remove IAP from the list */
   576 			    knownConfigs.remove(priv->network_id, iap);
   612                             notDiscoveredWLANConfigs.remove(priv->network_id, iap);
   577 #ifdef BEARER_MANAGEMENT_DEBUG
   613 #ifdef BEARER_MANAGEMENT_DEBUG
   578 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
   614 			    qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
   579 #endif
   615 #endif
   580 			    known_iaps.removeAt(k);
   616 			    known_iaps.removeAt(k);
   581 			    delete iap;
   617 			    delete iap;
   586 	    } else {
   622 	    } else {
   587 		qWarning() << "IAP" << iapid << "is missing in configuration.";
   623 		qWarning() << "IAP" << iapid << "is missing in configuration.";
   588 	    }
   624 	    }
   589 
   625 
   590 	} else {
   626 	} else {
   591 	    /* Non saved access point data */
   627             /* Non saved access point data */
   592 	    QByteArray scanned_ssid = ap.scan.network_id;
   628 	    QByteArray scanned_ssid = ap.scan.network_id;
   593 	    QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   629             if (!accessPointConfigurations.contains(scanned_ssid)) {
   594 	    QString hrs = scanned_ssid.data();
   630                 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   595 
   631                 QString hrs = scanned_ssid.data();
   596 	    cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
   632 
   597 	    cpPriv->isValid = true;
   633                 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
   634                 cpPriv->isValid = true;
   599 	    cpPriv->network_id = scanned_ssid;
   635                 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;
   636                 cpPriv->network_id = scanned_ssid;
   601 	    cpPriv->network_attrs = ap.scan.network_attrs;
   637                 cpPriv->iap_type = ap.scan.network_type;
   602 	    cpPriv->service_id = ap.scan.service_id;
   638                 cpPriv->network_attrs = ap.scan.network_attrs;
   603 	    cpPriv->service_type = ap.scan.service_type;
   639                 cpPriv->service_id = ap.scan.service_id;
   604 	    cpPriv->service_attrs = ap.scan.service_attrs;
   640                 cpPriv->service_type = ap.scan.service_type;
   605 	    cpPriv->manager = this;
   641                 cpPriv->service_attrs = ap.scan.service_attrs;
   606 
   642                 cpPriv->manager = this;
   607 	    cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   643 
   608 	    cpPriv->state = QNetworkConfiguration::Undefined;
   644                 cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   609 
   645                 cpPriv->state = QNetworkConfiguration::Undefined;
   610 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   646 
   611 	    accessPointConfigurations.insert(cpPriv->id, ptr);
   647                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   612 
   648                 accessPointConfigurations.insert(cpPriv->id, ptr);
   613 #ifdef BEARER_MANAGEMENT_DEBUG
   649 
   614 	    qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
   650     #ifdef BEARER_MANAGEMENT_DEBUG
   615 #endif
   651                 qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
   616 
   652     #endif
   617 	    QNetworkConfiguration item;
   653 
   618 	    item.d = ptr;
   654                 QNetworkConfiguration item;
   619 	    emit configurationAdded(item);
   655                 item.d = ptr;
   620 	}
   656                 emit configurationAdded(item);
   621       }
   657             } else {
   622 
   658                 knownConfigs.removeOne(scanned_ssid);
   623 
   659             }
   624     /* Remove non existing iaps since last update */
   660         }
       
   661     }
       
   662 
   625     if (!firstUpdate) {
   663     if (!firstUpdate) {
   626 	QHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
   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);
   627 	while (i.hasNext()) {
   667 	while (i.hasNext()) {
   628 	    i.next();
   668 	    i.next();
   629 	    SSIDInfo *iap = i.value();
   669 	    SSIDInfo *iap = i.value();
   630 	    QString iap_id = iap->iap_id;
   670 	    QString iap_id = iap->iap_id;
   631 	    //qDebug() << i.key() << ": " << iap_id;
   671 	    //qDebug() << i.key() << ": " << iap_id;
   632 
   672 
   633 	    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(iap_id);
   673             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iap_id);
   634 	    if (priv.data()) {
   674 	    if (priv.data()) {
   635 		priv->isValid = false;
   675                 // WLAN AccessPoint configuration could not be Discovered
   636 #ifdef BEARER_MANAGEMENT_DEBUG
   676                 // => Make sure that configuration state is Defined
   637 		qDebug() << "IAP" << iap_id << "was removed as it was not found in scan.";
   677                 if (priv->state > QNetworkConfiguration::Defined) {
   638 #endif
   678                     priv->state = QNetworkConfiguration::Defined;
   639 
   679                     configurationChanged(priv.data());
   640 		QNetworkConfiguration item;
   680                 }
   641 		item.d = priv;
   681 	    }
   642 		emit configurationRemoved(item);
   682 	}
   643 		configChanged(priv.data(), false);
   683 
   644 
   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);
   645 		//if we would have SNAP support we would have to remove the references
   692 		//if we would have SNAP support we would have to remove the references
   646 		//from existing ServiceNetworks to the removed access point configuration
   693 		//from existing ServiceNetworks to the removed access point configuration
   647 	    }
   694             }
   648 	}
   695         }
   649     }
   696     }
   650 
   697 
   651 
   698     QMutableHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
   652     QMutableHashIterator<QByteArray, SSIDInfo* > i(knownConfigs);
       
   653     while (i.hasNext()) {
   699     while (i.hasNext()) {
   654 	i.next();
   700 	i.next();
   655 	SSIDInfo *iap = i.value();
   701 	SSIDInfo *iap = i.value();
   656 	delete iap;
   702 	delete iap;
   657 	i.remove();
   703 	i.remove();
   661 	emit configurationUpdateComplete();
   707 	emit configurationUpdateComplete();
   662 
   708 
   663     if (firstUpdate)
   709     if (firstUpdate)
   664         firstUpdate = false;
   710         firstUpdate = false;
   665 }
   711 }
   666 
       
   667 
   712 
   668 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
   713 QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
   669 {
   714 {
   670     /* Here we just return [ANY] request to icd and let the icd decide which
   715     /* Here we just return [ANY] request to icd and let the icd decide which
   671      * IAP to connect.
   716      * IAP to connect.
   674     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
   719     if (userChoiceConfigurations.contains(OSSO_IAP_ANY))
   675         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
   720         item.d = userChoiceConfigurations.value(OSSO_IAP_ANY);
   676     return item;
   721     return item;
   677 }
   722 }
   678 
   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 }
   679 
   817 
   680 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   818 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   681 {
   819 {
   682     QTimer::singleShot(0, this, SLOT(updateConfigurations()));
   820     if (m_scanGoingOn) {
   683 }
   821         return;
   684 
   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 }
   685 
   897 
   686 void QNetworkConfigurationManagerPrivate::cleanup()
   898 void QNetworkConfigurationManagerPrivate::cleanup()
   687 {
   899 {
       
   900     if (m_scanGoingOn) {
       
   901         m_scanTimer.stop();
       
   902         m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
       
   903     }
   688     iapMonitor()->cleanup();
   904     iapMonitor()->cleanup();
   689 }
   905 }
   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 
   906 
   712 #include "qnetworkconfigmanager_maemo.moc"
   907 #include "qnetworkconfigmanager_maemo.moc"
   713 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
   908 #include "moc_qnetworkconfigmanager_maemo_p.cpp"
   714 
   909 
   715 QTM_END_NAMESPACE
   910 QTM_END_NAMESPACE