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/>.
20 #include <QApplication>
21 #include <QtCore/QTimerEvent>
22 #include <QtCore/QVariant>
23 #include <QtDBus/QDBusArgument>
24 #include <QtDBus/QDBusConnection>
25 #include <icd/dbus_api.h>
26 #include "connectionmanager.h"
29 ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
30 blocking_(true), stateReady_(false), connectionReady_(false), scanReady_(false),
31 connected_(false), timeout_(false), numberOfConnections_(0),
32 scannedConnections_(0), timer_(0), error_(NO_ERROR), connections_(0)
34 QDBusConnection systemBus = QDBusConnection::systemBus();
36 icd2interface_ = new QDBusInterface(ICD_DBUS_API_INTERFACE,
37 ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
40 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
41 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
42 this, SLOT(stateChange(const QDBusMessage&)));
44 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
45 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
46 this, SLOT(connectionChange(const QDBusMessage&)));
48 systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
49 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
50 this, SLOT(scanResult(const QDBusMessage&)));
54 ConnectionManager::~ConnectionManager()
56 QDBusConnection systemBus = QDBusConnection::systemBus();
58 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
59 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
60 this, SLOT(stateChange(const QDBusMessage&)));
62 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
63 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
64 this, SLOT(connectionChange(const QDBusMessage&)));
66 systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
67 ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
68 this, SLOT(scanResult(const QDBusMessage&)));
71 void ConnectionManager::setBlocking(bool value)
76 bool ConnectionManager::connect()
78 connectionReady_ = false;
79 unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
80 icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
84 waitSignal(&connectionReady_);
91 bool ConnectionManager::connect(ConnectionManager::Connection const& connection)
93 return connect(connection.id);
96 bool ConnectionManager::connect(QString const& id)
98 QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.icd",
102 QList<QVariant> arguments;
104 arguments.append(QVariant(id));
106 unsigned int val = 0;
108 arguments.append(QVariant(val));
110 msg.setArguments(arguments);
112 QDBusMessage rep = QDBusConnection::systemBus().call(msg);
114 if(rep.type() == QDBusMessage::ErrorMessage)
116 if(rep.errorName() == "com.nokia.icd.error.invalid_iap")
118 error_ = INVALID_IAP;
122 error_ = UNKNOWN_ERROR;
131 bool ConnectionManager::getBestConnection(Connection& connection)
133 bool blockingValue = blocking_;
137 QList<Connection> connections;
139 if(!scanConnections(connections))
144 blocking_ = blockingValue;
146 if(connections.size() == 0)
148 qDebug() << "No connections";
149 error_ = NO_AVAILABLE_CONNECTIONS;
153 int biggestWlan = -1;
154 int biggestGprs = -1;
158 for(int i = 0; i < connections.size(); i++)
160 switch(connections.at(i).type)
163 if(connections.at(i).strength > biggestWlan)
165 biggestWlan = connections.at(i).strength;
171 if(connections.at(i).strength > biggestGprs)
173 biggestGprs = connections.at(i).strength;
179 qDebug() << "Unknown connection type";
185 connection = connections.at(bestWlan);
188 else if(bestGprs >= 0)
190 connection = connections.at(bestGprs);
195 error_ = NO_AVAILABLE_CONNECTIONS;
201 bool ConnectionManager::autoConnect()
205 if(!getBestConnection(best))
210 qDebug() << "Best connection: " << best.name;
212 return connect(best.id);
216 bool ConnectionManager::disconnect(bool force)
218 // Forced disconnect is not allowed if connection
219 // was not initialized by this class
220 if(!connected_ && force)
225 connectionReady_ = false;
230 flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_UI_EVENT);
234 flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
237 icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
242 bool ConnectionManager::isConnected()
245 QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
247 unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
249 if(numOfReplies == 0)
251 emit isConnectedReply(false);
257 waitSignal(&stateReady_);
264 bool ConnectionManager::scanConnections(QList<ConnectionManager::Connection>& connections)
266 unsigned int flags = static_cast<unsigned int>(ICD_SCAN_REQUEST_ACTIVE_SAVED);
268 scannedConnections_ = 0;
269 connections_ = &connections;
270 QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_SCAN_REQ, QVariant(flags));
272 numberOfConnections_ = rep.arguments().value(0).toList().size();
274 if(numberOfConnections_ == 0)
282 bool ret = waitSignal(&scanReady_);
290 ConnectionManager::NetworkMode ConnectionManager::getNetworkMode()
292 QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.phone.net",
293 "/com/nokia/phone/net",
295 "get_registration_status");
297 QDBusMessage rep = QDBusConnection::systemBus().call(msg);
299 if(rep.type() == QDBusMessage::ErrorMessage)
301 qDebug() << rep.errorMessage();
303 return NETWORK_UNKNOWN;
306 char services = rep.arguments().value(6).toChar().toAscii();
308 qDebug() << services;
314 else if(services & 0x04)
318 else if(services & 0x01)
322 else if(services & 0x02)
327 return NETWORK_UNKNOWN;
330 ConnectionManager::Error ConnectionManager::error() const
335 void ConnectionManager::stateChange(const QDBusMessage& rep)
337 unsigned int status = rep.arguments().value(7).value<unsigned int>();
341 case ICD_STATE_CONNECTING:
343 case ICD_STATE_CONNECTED:
347 case ICD_STATE_DISCONNECTING:
349 case ICD_STATE_DISCONNECTED:
353 case ICD_STATE_LIMITED_CONN_ENABLED:
357 case ICD_STATE_LIMITED_CONN_DISABLED:
361 case ICD_STATE_SEARCH_START:
363 case ICD_STATE_SEARCH_STOP:
365 case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
368 qDebug() << "Unknown connection status";
374 emit isConnectedReply(connected_);
379 void ConnectionManager::connectionChange(const QDBusMessage& rep)
381 unsigned int status = rep.arguments().value(6).value<unsigned int>();
385 case ICD_CONNECTION_SUCCESSFUL:
387 connectionReady_ = true;
389 case ICD_CONNECTION_NOT_CONNECTED:
391 connectionReady_ = true;
393 case ICD_CONNECTION_DISCONNECTED:
395 connectionReady_ = true;
398 qDebug() << "Unknown connection status";
404 emit connectReply(connected_);
408 void ConnectionManager::scanResult(const QDBusMessage& rep)
415 QList<QVariant> args = rep.arguments();
417 unsigned int status = args.value(0).value<unsigned int>();
419 if(status == ICD_SCAN_COMPLETE)
421 scannedConnections_++;
424 if(scannedConnections_ >= numberOfConnections_)
432 if(status != ICD_SCAN_NEW)
437 Connection connection;
438 connection.id = QString(args.value(10).toByteArray());
439 connection.name = args.value(8).toString();
440 connection.strength = args.value(11).toInt();
442 QString type = args.value(7).toString();
446 connection.type = GPRS;
448 else if(type == "WLAN_INFRA" || type == "WLAN_ADHOC")
450 connection.type = WLAN;
454 qDebug() << "Unknown connection type: " << type;
458 emit newConnection(connection);
460 connections_->push_back(connection);
463 bool ConnectionManager::waitSignal(bool* ready)
466 timer_ = startTimer(TIMEOUT);
468 while(!*ready && !timeout_)
470 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
475 return *ready || !timeout_;
478 void ConnectionManager::timerEvent(QTimerEvent* event)
485 qDebug() << "Connection request timed out";