2 * This file is part of Jenirok.
4 * Jenirok is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Jenirok is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Jenirok. If not, see <http://www.gnu.org/licenses/>.
19 #include <QtCore/QDebug>
20 #include <QtCore/QTimerEvent>
21 #include <QtCore/QVariant>
22 #include <QtCore/QStringList>
23 #include <QtGui/QApplication>
24 #include <QtDBus/QDBusArgument>
25 #include <QtDBus/QDBusConnection>
26 #include <icd/dbus_api.h>
27 #include "connectionmanager.h"
29 bool ConnectionManager::connected_ = false;
31 ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
32 stateReady_(false), connectionReady_(false), scanReady_(false),
33 timeout_(false), numberOfConnections_(0),
34 scannedConnections_(0), timer_(0), searchType_(NO_TYPE), error_(NO_ERROR), connections_(0)
36 QDBusConnection systemBus = QDBusConnection::systemBus();
38 icd2interface_ = new QDBusInterface(ICD_DBUS_API_INTERFACE,
39 ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
42 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
43 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
44 this, SLOT(stateChange(const QDBusMessage&)));
46 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
47 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
48 this, SLOT(connectionChange(const QDBusMessage&)));
50 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
51 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
52 this, SLOT(scanResult(const QDBusMessage&)));
56 ConnectionManager::~ConnectionManager()
58 QDBusConnection systemBus = QDBusConnection::systemBus();
60 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
61 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
62 this, SLOT(stateChange(const QDBusMessage&)));
64 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
65 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
66 this, SLOT(connectionChange(const QDBusMessage&)));
68 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
69 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
70 this, SLOT(scanResult(const QDBusMessage&)));
73 bool ConnectionManager::connect()
75 connectionReady_ = false;
76 unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
77 icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
79 waitSignal(&connectionReady_);
83 sleep(WAIT_AFTER_CONNECT);
89 bool ConnectionManager::connect(ConnectionManager::Connection const& connection)
91 return connect(connection.id);
94 bool ConnectionManager::connect(QString const& id)
96 QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.icd",
100 QList<QVariant> arguments;
102 arguments.append(QVariant(id));
104 unsigned int val = 0;
106 arguments.append(QVariant(val));
108 msg.setArguments(arguments);
110 QDBusMessage rep = QDBusConnection::systemBus().call(msg);
112 if(rep.type() == QDBusMessage::ErrorMessage)
114 if(rep.errorName() == "com.nokia.icd.error.invalid_iap")
116 error_ = INVALID_IAP;
120 error_ = UNKNOWN_ERROR;
130 sleep(WAIT_AFTER_CONNECT);
135 bool ConnectionManager::getBestConnection(Connection& connection, ConnectionType type)
137 QList<Connection> connections;
139 if(!scanConnections(connections))
141 qDebug() << "Unable to scan connections";
145 if(connections.size() == 0)
147 error_ = NO_AVAILABLE_CONNECTIONS;
151 int biggestWlan = -1;
152 int biggestGprs = -1;
156 for(int i = 0; i < connections.size(); i++)
158 switch(connections.at(i).type)
161 if(type != GPRS && connections.at(i).strength > biggestWlan)
163 biggestWlan = connections.at(i).strength;
169 if(type != WLAN && connections.at(i).strength > biggestGprs)
171 biggestGprs = connections.at(i).strength;
177 qDebug() << "Unknown connection type";
183 connection = connections.at(bestWlan);
186 else if(bestGprs >= 0)
188 connection = connections.at(bestGprs);
193 error_ = NO_AVAILABLE_CONNECTIONS;
199 bool ConnectionManager::disconnect(bool force)
203 QDBusMessage msg = QDBusMessage::createSignal("/com/nokia/icd_ui",
207 QList<QVariant> arguments;
209 arguments.append(QVariant(val));
210 msg.setArguments(arguments);
212 bool ret = QDBusConnection::systemBus().send(msg);
222 connectionReady_ = false;
225 flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
227 icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
232 bool ConnectionManager::isConnected()
235 QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
237 unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
239 if(numOfReplies == 0)
244 waitSignal(&stateReady_);
248 bool ConnectionManager::scanConnections(QList<ConnectionManager::Connection>& connections,
249 ConnectionManager::ConnectionType type)
251 unsigned int flags = static_cast<unsigned int>(ICD_SCAN_REQUEST_ACTIVE_SAVED);
253 scannedConnections_ = 0;
254 connections_ = &connections;
257 QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_SCAN_REQ,
260 numberOfConnections_ = rep.arguments().value(0).toList().size();
262 // For some reason, during call icd2 doesn't return any connections
263 // it is going to scan. However, it still scans them so use default value
265 if(numberOfConnections_ == 0)
267 numberOfConnections_ = 2;
270 bool ret = waitSignal(&scanReady_);
275 ConnectionManager::Error ConnectionManager::error() const
280 void ConnectionManager::stateChange(const QDBusMessage& rep)
282 unsigned int status = rep.arguments().value(7).value<unsigned int>();
286 case ICD_STATE_CONNECTING:
288 case ICD_STATE_CONNECTED:
292 case ICD_STATE_DISCONNECTING:
294 case ICD_STATE_DISCONNECTED:
298 case ICD_STATE_LIMITED_CONN_ENABLED:
302 case ICD_STATE_LIMITED_CONN_DISABLED:
306 case ICD_STATE_SEARCH_START:
308 case ICD_STATE_SEARCH_STOP:
310 case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
313 qDebug() << "Unknown connection status";
319 void ConnectionManager::connectionChange(const QDBusMessage& rep)
321 unsigned int status = rep.arguments().value(6).value<unsigned int>();
325 case ICD_CONNECTION_SUCCESSFUL:
327 connectionReady_ = true;
329 case ICD_CONNECTION_NOT_CONNECTED:
331 connectionReady_ = true;
333 case ICD_CONNECTION_DISCONNECTED:
335 connectionReady_ = true;
338 qDebug() << "Unknown connection status";
344 void ConnectionManager::scanResult(const QDBusMessage& rep)
351 QList<QVariant> args = rep.arguments();
353 unsigned int status = args.value(0).value<unsigned int>();
355 if(status == ICD_SCAN_COMPLETE)
357 scannedConnections_++;
360 if(scannedConnections_ >= numberOfConnections_)
367 if(status != ICD_SCAN_NEW && status != ICD_SCAN_NOTIFY)
372 Connection connection;
374 QString type = args.value(7).toString();
378 if(searchType_ == WLAN)
383 connection.type = GPRS;
385 else if(type == "WLAN_INFRA" || type == "WLAN_ADHOC")
387 if(searchType_ == GPRS)
392 connection.type = WLAN;
396 qDebug() << "Unknown connection type: " << type;
400 connection.id = QString(args.value(10).toByteArray());
401 connection.name = args.value(8).toString();
402 connection.strength = args.value(11).toInt();
404 for(int i = 0; i < connections_->size(); i++)
406 if(connections_->at(i).id == connection.id)
408 if(status == ICD_SCAN_NEW)
410 connections_->replace(i, connection);
417 connections_->push_back(connection);
420 bool ConnectionManager::waitSignal(bool* ready)
423 timer_ = startTimer(TIMEOUT);
425 while(!*ready && !timeout_)
427 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
434 qDebug() << "Connection request timed out";
437 return *ready || !timeout_;
440 void ConnectionManager::sleep(unsigned int ms)
443 timer_ = startTimer(ms);
447 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
453 void ConnectionManager::timerEvent(QTimerEvent* event)