*
*/
-#include <QDebug>
-#include <glib-object.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <QtCore/QDebug>
+#include <QtCore/QTimerEvent>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+#include <QtGui/QApplication>
+#include <QtDBus/QDBusArgument>
+#include <QtDBus/QDBusConnection>
+#include <icd/dbus_api.h>
#include "connectionmanager.h"
-ConnectionManager* ConnectionManager::instance_ = 0;
-ConnectionManager::ConnectionManager(): connection_(0), connected_(false)
+ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
+blocking_(true), stateReady_(false), connectionReady_(false), scanReady_(false),
+connected_(false), timeout_(false), numberOfConnections_(0),
+scannedConnections_(0), timer_(0), error_(NO_ERROR), connections_(0)
{
- DBusError err;
- DBusConnection* conn;
- dbus_error_init(&err);
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+ QDBusConnection systemBus = QDBusConnection::systemBus();
- if(conn)
+ icd2interface_ = new QDBusInterface(ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+ systemBus, this);
+
+ systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
+ this, SLOT(stateChange(const QDBusMessage&)));
+
+ systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
+ this, SLOT(connectionChange(const QDBusMessage&)));
+
+ systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
+ this, SLOT(scanResult(const QDBusMessage&)));
+
+}
+
+ConnectionManager::~ConnectionManager()
+{
+ QDBusConnection systemBus = QDBusConnection::systemBus();
+
+ systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
+ this, SLOT(stateChange(const QDBusMessage&)));
+
+ systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
+ this, SLOT(connectionChange(const QDBusMessage&)));
+
+ systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
+ this, SLOT(scanResult(const QDBusMessage&)));
+}
+
+void ConnectionManager::setBlocking(bool value)
+{
+ blocking_ = value;
+}
+
+bool ConnectionManager::connect()
+{
+ connectionReady_ = false;
+ unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+ icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
+
+ if(blocking_)
{
- dbus_connection_setup_with_g_main(conn, NULL);
+ waitSignal(&connectionReady_);
+ return connected_;
}
- else
+
+ return true;
+}
+
+bool ConnectionManager::connect(ConnectionManager::Connection const& connection)
+{
+ return connect(connection.id);
+}
+
+bool ConnectionManager::connect(QString const& id)
+{
+ QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.icd",
+ "/com/nokia/icd",
+ "com.nokia.icd",
+ "connect");
+ QList<QVariant> arguments;
+
+ arguments.append(QVariant(id));
+
+ unsigned int val = 0;
+
+ arguments.append(QVariant(val));
+
+ msg.setArguments(arguments);
+
+ QDBusMessage rep = QDBusConnection::systemBus().call(msg);
+
+ if(rep.type() == QDBusMessage::ErrorMessage)
{
- qDebug() << "Unable to connect to DBUS: " << err.message;
- dbus_error_free(&err);
+ if(rep.errorName() == "com.nokia.icd.error.invalid_iap")
+ {
+ error_ = INVALID_IAP;
+ }
+ else
+ {
+ error_ = UNKNOWN_ERROR;
+ }
+
+ return false;
}
- connection_ = con_ic_connection_new();
+ return true;
+}
+
+bool ConnectionManager::getBestConnection(Connection& connection, ConnectionType type)
+{
+ bool blockingValue = blocking_;
- g_signal_connect(G_OBJECT(connection_), "connection-event", G_CALLBACK(connectionHandler), NULL);
+ blocking_ = true;
+ QList<Connection> connections;
+
+ if(!scanConnections(connections))
+ {
+ return false;
+ }
+
+ blocking_ = blockingValue;
+
+ if(connections.size() == 0)
+ {
+ error_ = NO_AVAILABLE_CONNECTIONS;
+ return false;
+ }
+
+ int biggestWlan = -1;
+ int biggestGprs = -1;
+ int bestWlan = -1;
+ int bestGprs = -1;
+
+ for(int i = 0; i < connections.size(); i++)
+ {
+ switch(connections.at(i).type)
+ {
+ case WLAN:
+ if(type != GPRS && connections.at(i).strength > biggestWlan)
+ {
+ biggestWlan = connections.at(i).strength;
+ bestWlan = i;
+ }
+ break;
+
+ case GPRS:
+ if(type != WLAN && connections.at(i).strength > biggestGprs)
+ {
+ biggestGprs = connections.at(i).strength;
+ bestGprs = i;
+ }
+ break;
+
+ default:
+ qDebug() << "Unknown connection type";
+ }
+ }
+
+ if(bestWlan >= 0)
+ {
+ connection = connections.at(bestWlan);
+ return true;
+ }
+ else if(bestGprs >= 0)
+ {
+ connection = connections.at(bestGprs);
+ return true;
+ }
+ else
+ {
+ error_ = NO_AVAILABLE_CONNECTIONS;
+ return false;
+ }
}
-ConnectionManager& ConnectionManager::instance()
+bool ConnectionManager::disconnect(bool force)
{
- if(!instance_)
+ // Forced disconnect is not allowed if connection
+ // was not initialized by this class
+ if(!connected_ && force)
{
- instance_ = new ConnectionManager;
+ return false;
}
- return *instance_;
+ connectionReady_ = false;
+ unsigned int flags;
+
+ if(force)
+ {
+ flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_UI_EVENT);
+ }
+ else
+ {
+ flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+ }
+
+ icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
+ connected_ = false;
+ return true;
}
-bool ConnectionManager::connect()
+bool ConnectionManager::isConnected()
{
- return con_ic_connection_connect(connection_, CON_IC_CONNECT_FLAG_NONE);
+ stateReady_ = false;
+ QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
+
+ unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
+
+ if(numOfReplies == 0)
+ {
+ emit isConnectedReply(false);
+ return false;
+ }
+
+ if(blocking_)
+ {
+ waitSignal(&stateReady_);
+ return connected_;
+ }
+
+ return true;
}
-bool ConnectionManager::disconnect()
+bool ConnectionManager::scanConnections(QList<ConnectionManager::Connection>& connections,
+ ConnectionManager::ConnectionType type)
{
- return con_ic_connection_disconnect(connection_);
+ unsigned int flags = static_cast<unsigned int>(ICD_SCAN_REQUEST_ACTIVE_SAVED);
+ scanReady_ = false;
+ scannedConnections_ = 0;
+ connections_ = &connections;
+
+ QStringList networks;
+
+ switch(type)
+ {
+ case WLAN:
+ networks << "WLAN_INFRA" << "WLAN_ADHOC";
+ break;
+ case GPRS:
+ networks << "GPRS";
+ break;
+ default:
+ break;
+ }
+
+ QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_SCAN_REQ,
+ QVariant(flags),
+ QVariant(networks));
+
+ numberOfConnections_ = rep.arguments().value(0).toList().size();
+
+ if(numberOfConnections_ == 0)
+ {
+ connections_ = 0;
+ qDebug() << "No connections";
+ return false;
+ }
+
+ if(blocking_)
+ {
+ bool ret = waitSignal(&scanReady_);
+ connections_ = 0;
+ return ret;
+ }
+
+ return true;
}
-bool ConnectionManager::isConnected()
+ConnectionManager::Error ConnectionManager::error() const
{
- return connected_;
+ return error_;
}
-void ConnectionManager::connectionHandler(ConIcConnection *connection,
- ConIcConnectionEvent *event,
- gpointer user_data)
-{
- Q_UNUSED(connection);
- Q_UNUSED(user_data);
- ConIcConnectionStatus status = con_ic_connection_event_get_status(event);
+void ConnectionManager::stateChange(const QDBusMessage& rep)
+{
+ unsigned int status = rep.arguments().value(7).value<unsigned int>();
switch(status)
{
-
- case CON_IC_STATUS_CONNECTED:
- qDebug() << "Connected";
- instance_->emit connected();
- instance_->connected_ = true;
+ case ICD_STATE_CONNECTING:
break;
-
- case CON_IC_STATUS_DISCONNECTING:
- case CON_IC_STATUS_NETWORK_UP:
+ case ICD_STATE_CONNECTED:
+ connected_ = true;
+ stateReady_ = true;
+ break;
+ case ICD_STATE_DISCONNECTING:
+ break;
+ case ICD_STATE_DISCONNECTED:
+ connected_ = false;
+ stateReady_ = true;
+ break;
+ case ICD_STATE_LIMITED_CONN_ENABLED:
+ connected_ = true;
+ stateReady_ = true;
+ break;
+ case ICD_STATE_LIMITED_CONN_DISABLED:
+ connected_ = false;
+ stateReady_ = true;
+ break;
+ case ICD_STATE_SEARCH_START:
break;
+ case ICD_STATE_SEARCH_STOP:
+ break;
+ case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
+ break;
+ default:
+ qDebug() << "Unknown connection status";
+ break;
+ }
- case CON_IC_STATUS_DISCONNECTED:
- ConIcConnectionError err = con_ic_connection_event_get_error(event);
- switch(err)
- {
- case CON_IC_CONNECTION_ERROR_NONE:
- case CON_IC_CONNECTION_ERROR_USER_CANCELED:
- qDebug() << "Disconnected";
- instance_->emit disconnected();
- instance_->connected_ = false;
- break;
-
- case CON_IC_CONNECTION_ERROR_INVALID_IAP:
- qDebug() << "Invalid IAP";
- instance_->emit error("Invalid IAP");
- break;
-
- case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
- qDebug() << "Connection failed";
- instance_->emit error("Connection failed");
- break;
-
- default:
- break;
- }
+ if(stateReady_)
+ {
+ emit isConnectedReply(connected_);
+ }
+
+}
+
+void ConnectionManager::connectionChange(const QDBusMessage& rep)
+{
+ unsigned int status = rep.arguments().value(6).value<unsigned int>();
+
+ switch(status)
+ {
+ case ICD_CONNECTION_SUCCESSFUL:
+ connected_ = true;
+ connectionReady_ = true;
break;
+ case ICD_CONNECTION_NOT_CONNECTED:
+ connected_ = false;
+ connectionReady_ = true;
+ break;
+ case ICD_CONNECTION_DISCONNECTED:
+ connected_ = false;
+ connectionReady_ = true;
+ break;
+ default:
+ qDebug() << "Unknown connection status";
+ break;
+ }
+
+ if(connectionReady_)
+ {
+ emit connectReply(connected_);
+ }
+}
+
+void ConnectionManager::scanResult(const QDBusMessage& rep)
+{
+ if(!connections_)
+ {
+ return;
+ }
+
+ QList<QVariant> args = rep.arguments();
+
+ unsigned int status = args.value(0).value<unsigned int>();
+
+ if(status == ICD_SCAN_COMPLETE)
+ {
+ scannedConnections_++;
}
+
+ if(scannedConnections_ >= numberOfConnections_)
+ {
+ scanReady_ = true;
+ connections_ = 0;
+ emit scanReady();
+ return;
+ }
+
+ if(status != ICD_SCAN_NEW)
+ {
+ return;
+ }
+
+ Connection connection;
+ connection.id = QString(args.value(10).toByteArray());
+ connection.name = args.value(8).toString();
+ connection.strength = args.value(11).toInt();
+
+ QString type = args.value(7).toString();
+
+ if(type == "GPRS")
+ {
+ connection.type = GPRS;
+ }
+ else if(type == "WLAN_INFRA" || type == "WLAN_ADHOC")
+ {
+ connection.type = WLAN;
+ }
+ else
+ {
+ qDebug() << "Unknown connection type: " << type;
+ return;
+ }
+
+ emit newConnection(connection);
+
+ connections_->push_back(connection);
+}
+
+bool ConnectionManager::waitSignal(bool* ready)
+{
+ timeout_ = false;
+ timer_ = startTimer(TIMEOUT);
+
+ while(!*ready && !timeout_)
+ {
+ QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
+ }
+
+ killTimer(timer_);
+
+ return *ready || !timeout_;
+}
+
+void ConnectionManager::timerEvent(QTimerEvent* event)
+{
+ Q_UNUSED(event);
+ killTimer(timer_);
+ timeout_ = true;
+ timer_ = 0;
+
+ qDebug() << "Connection request timed out";
}