From 5a6cf73142c022399b7643d54ed3915192a41cc8 Mon Sep 17 00:00:00 2001 From: "Petri M. Gerdt" Date: Tue, 15 Jan 2013 15:42:27 +0200 Subject: [PATCH] Add oFono based cellular network information classes The classes provide the functionality that the closed source Harmattan CellularQt used to provide. These classes do not contain any code from CellularQt, only the interface has been partially replicated based on docs from http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libcellular-qt/ --- src/server/modemwatcher.cpp | 83 ++++++++++++++ src/server/modemwatcher.h | 34 ++++++ src/server/networkoperator.cpp | 88 ++++++++++++++ src/server/networkoperator.h | 42 +++++++ src/server/networkregistrationwatcher.cpp | 85 ++++++++++++++ src/server/networkregistrationwatcher.h | 30 +++++ src/server/networktime.cpp | 133 ++++++++++++++++++++++ src/server/networktime.h | 41 +++++++ src/server/networktimeinfo.cpp | 88 ++++++++++++++ src/server/networktimeinfo.h | 37 ++++++ src/server/networktimewatcher.cpp | 62 ++++++++++ src/server/networktimewatcher.h | 32 ++++++ src/server/ofonomodemmanager.cpp | 103 +++++++++++++++++ src/server/ofonomodemmanager.h | 34 ++++++ 14 files changed, 892 insertions(+) create mode 100644 src/server/modemwatcher.cpp create mode 100644 src/server/modemwatcher.h create mode 100644 src/server/networkoperator.cpp create mode 100644 src/server/networkoperator.h create mode 100644 src/server/networkregistrationwatcher.cpp create mode 100644 src/server/networkregistrationwatcher.h create mode 100644 src/server/networktime.cpp create mode 100644 src/server/networktime.h create mode 100644 src/server/networktimeinfo.cpp create mode 100644 src/server/networktimeinfo.h create mode 100644 src/server/networktimewatcher.cpp create mode 100644 src/server/networktimewatcher.h create mode 100644 src/server/ofonomodemmanager.cpp create mode 100644 src/server/ofonomodemmanager.h diff --git a/src/server/modemwatcher.cpp b/src/server/modemwatcher.cpp new file mode 100644 index 0000000..4301be0 --- /dev/null +++ b/src/server/modemwatcher.cpp @@ -0,0 +1,83 @@ +#include +#include + +#include + +#include "modemwatcher.h" + +ModemWatcher::ModemWatcher(const QString objectPath, const QString interface, QObject *parent) : + QObject(parent), m_objectPath(objectPath), m_interface(interface) +{ + QDBusConnection::systemBus().connect("org.ofono", m_objectPath, + "org.ofono.Modem", "PropertyChanged", + this, SLOT(onModemPropertyChanged(QString, QDBusVariant))); + + QDBusMessage request = QDBusMessage::createMethodCall("org.ofono", m_objectPath, + "org.ofono.Modem", + "GetProperties"); + + QDBusReply reply = QDBusConnection::systemBus().call(request); + if (reply.error().isValid()) { + log_error("DBus call to interface %s function GetProperties of path %s failed: %s", + m_interface.toStdString().c_str(), + m_objectPath.toStdString().c_str(), + reply.error().message().toStdString().c_str()); + } else { + QVariantMap properties = reply; + checkInterfaceAvailability(properties.value("Interfaces")); + } +} + +ModemWatcher::~ModemWatcher() +{ + QDBusConnection::systemBus().disconnect("org.ofono", m_objectPath, + "org.ofono.Modem", "PropertyChanged", + this, SLOT(onModemPropertyChanged(QString, QDBusVariant))); +} + +bool ModemWatcher::interfaceAvailable() const +{ + return m_interfaceAvailable; +} + +QString ModemWatcher::objectPath() const +{ + return m_objectPath; +} + +QString ModemWatcher::interface() const +{ + return m_interface; +} + +// Checks if the interface stored in m_interface is present in +// list of interfaces stored in parameter variant. +// Changes m_interfaceAvailable to reflect interface presence in +// the list: true indicates that the interface is in the list, false +// indicates that it is not. If m_interfaceAvailable was changed, +// then returns true, otherwise returns false. +bool ModemWatcher::checkInterfaceAvailability(QVariant variant) +{ + if (variant.type() == QVariant::StringList) { + QStringList list = variant.toStringList(); + bool available = list.contains(m_interface); + if (available != m_interfaceAvailable) { + m_interfaceAvailable = available; + return true; + } + } + + return false; +} + +void ModemWatcher::onModemPropertyChanged(QString name, QDBusVariant value) +{ + if (name.compare("Interfaces") == 0) { + if (checkInterfaceAvailability(value.variant())) { + log_debug("interface %s availability changed: %s", + m_interface.toStdString().c_str(), + m_interfaceAvailable ? "available" : "not available"); + emit interfaceAvailableChanged(m_interfaceAvailable); + } + } +} diff --git a/src/server/modemwatcher.h b/src/server/modemwatcher.h new file mode 100644 index 0000000..29fe665 --- /dev/null +++ b/src/server/modemwatcher.h @@ -0,0 +1,34 @@ +#ifndef MODEMWATCHER_H +#define MODEMWATCHER_H + +#include +#include +#include + +class QDBusInterface; +class QDBusPendingCallWatcher; + +class ModemWatcher : public QObject +{ + Q_OBJECT + +public: + explicit ModemWatcher(const QString objectPath, const QString interface, QObject *parent = 0); + ~ModemWatcher(); + bool interfaceAvailable() const; + QString objectPath() const; + QString interface() const; + +signals: + void interfaceAvailableChanged(bool available); + +private: + QString m_objectPath; + QString m_interface; + bool m_interfaceAvailable; + bool checkInterfaceAvailability(QVariant variant); + +private slots: + void onModemPropertyChanged(QString objectPath, QDBusVariant value); +}; +#endif // MODEMWATCHER_H diff --git a/src/server/networkoperator.cpp b/src/server/networkoperator.cpp new file mode 100644 index 0000000..d40bb13 --- /dev/null +++ b/src/server/networkoperator.cpp @@ -0,0 +1,88 @@ +#include + +#include + +#include "networkoperator.h" +#include "networkregistrationwatcher.h" + +NetworkOperator::NetworkOperator(QObject *parent) : + QObject(parent), m_mccUpdated(false), m_mncUpdated(false) +{ + foreach (const QString objectPath, m_modemManager.getModems()) + onModemAdded(objectPath); + + QObject::connect(&m_modemManager, SIGNAL(modemAdded(QString)), + this, SLOT(onModemAdded(QString))); + + QObject::connect(&m_modemManager, SIGNAL(modemRemoved(QString)), + this, SLOT(onModemRemoved(QString))); +} + +QString NetworkOperator::mnc() const +{ + return m_mnc; +} + +QString NetworkOperator::mcc() const +{ + return m_mcc; +} + +bool NetworkOperator::isValid() const +{ + return !(m_mcc.isEmpty() || m_mnc.isEmpty()); +} + +void NetworkOperator::onModemAdded(QString objectPath) +{ + if (!m_watcherMap.contains(objectPath)) { + NetworkRegistrationWatcher *watcher = new NetworkRegistrationWatcher(objectPath, this); + QObject::connect(watcher, SIGNAL(propertyChanged(QString, QString, QVariant)), + this, SLOT(onWatcherPropertyChanged(QString, QString, QVariant))); + watcher->getProperties(); + m_watcherMap.insert(objectPath, watcher); + } +} + +void NetworkOperator::onModemRemoved(QString objectPath) +{ + if (m_watcherMap.contains(objectPath)) { + NetworkRegistrationWatcher *watcher = m_watcherMap.value(objectPath); + m_watcherMap.remove(objectPath); + delete watcher; + } +} + +void NetworkOperator::onWatcherPropertyChanged(QString objectPath, QString name, QVariant value) +{ + if (m_currentObjectPath.compare(objectPath) != 0 + && (name.compare("MobileCountryCode") == 0 || name.compare("MobileNetworkCode") == 0)) { + m_currentObjectPath = objectPath; + m_mccUpdated = false; + m_mncUpdated = false; + m_mnc = ""; + m_mcc = ""; + } + + if (name.compare("MobileCountryCode") == 0) { + if (value.type() == QVariant::String) { + m_mcc = value.toString(); + m_mccUpdated = true; + } + } else if (name.compare("MobileNetworkCode") == 0) { + if (value.type() == QVariant::String) { + m_mnc = value.toString(); + m_mncUpdated = true; + } + } + + if (m_mccUpdated && m_mncUpdated) { + m_mccUpdated = false; + m_mncUpdated = false; + log_debug("operator changed: MNC: %s, MCC: %s, modem: %s", + m_mnc.toStdString().c_str(), + m_mcc.toStdString().c_str(), + objectPath.toStdString().c_str()); + emit operatorChanged(m_mnc, m_mcc); + } +} diff --git a/src/server/networkoperator.h b/src/server/networkoperator.h new file mode 100644 index 0000000..54e4659 --- /dev/null +++ b/src/server/networkoperator.h @@ -0,0 +1,42 @@ +#ifndef NETWORKOPERATOR_H +#define NETWORKOPERATOR_H + +#include +#include +#include + +#include "ofonomodemmanager.h" + +class NetworkRegistrationWatcher; + +// See http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libcellular-qt/classCellular_1_1NetworkOperator.html +class NetworkOperator : public QObject +{ + Q_OBJECT + +public: + explicit NetworkOperator(QObject *parent = 0); + QString mnc() const; + QString mcc() const; + bool isValid() const; + +signals: + void operatorChanged(const QString &mnc, const QString &mcc); + +private: + QString m_mnc; + QString m_mcc; + bool m_mccUpdated; + bool m_mncUpdated; + bool m_valid; + QString m_currentObjectPath; + OfonoModemManager m_modemManager; + QMap m_watcherMap; + +private slots: + void onModemAdded(QString objectPath); + void onModemRemoved(QString objectPath); + void onWatcherPropertyChanged(QString objectPath, QString name, QVariant value); +}; + +#endif // NETWORKOPERATOR_H diff --git a/src/server/networkregistrationwatcher.cpp b/src/server/networkregistrationwatcher.cpp new file mode 100644 index 0000000..a8bd04c --- /dev/null +++ b/src/server/networkregistrationwatcher.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#include + +#include "networkregistrationwatcher.h" + +NetworkRegistrationWatcher::NetworkRegistrationWatcher(const QString path, QObject *parent) : + ModemWatcher(path, "org.ofono.NetworkRegistration", parent) +{ + QDBusConnection::systemBus().connect("org.ofono", objectPath(), + interface(), "PropertyChanged", + this, SLOT(onPropertyChanged(QString, QDBusVariant))); + + QObject::connect(this, SIGNAL(interfaceAvailableChanged(bool)), + this, SLOT(getPropertiesAsync())); +} + +NetworkRegistrationWatcher::~NetworkRegistrationWatcher() +{ + QDBusConnection::systemBus().disconnect("org.ofono", objectPath(), + interface(), "PropertyChanged", + this, SLOT(onPropertyChanged(QString, QDBusVariant))); +} + +void NetworkRegistrationWatcher::getProperties() +{ + if (!interfaceAvailable()) + return; + + QDBusMessage request = QDBusMessage::createMethodCall("org.ofono", objectPath(), interface(), + "GetProperties"); + QDBusReply reply = QDBusConnection::systemBus().call(request); + if (reply.error().isValid()) { + log_error("DBus call to interface %s function GetProperties of path %s failed: %s", + interface().toStdString().c_str(), + objectPath().toStdString().c_str(), + reply.error().message().toStdString().c_str()); + return; + } + + QVariantMap map = reply.value(); + foreach (const QString &key, map.keys()) + emit propertyChanged(objectPath(), key, map.value(key)); +} + +void NetworkRegistrationWatcher::getPropertiesAsync() +{ + if (!interfaceAvailable()) + return; + + QDBusInterface dbusInterface("org.ofono", objectPath(), interface(), QDBusConnection::systemBus()); + if (dbusInterface.isValid()) { + QDBusPendingCall async = dbusInterface.asyncCall("GetProperties"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getPropertiesAsyncCallback(QDBusPendingCallWatcher*))); + } else { + log_error("Dbus interface %s of path %s is invalid.", + interface().toStdString().c_str(), + objectPath().toStdString().c_str()); + } +} + +void NetworkRegistrationWatcher::getPropertiesAsyncCallback(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply reply = *watcher; + if (reply.error().isValid()) { + log_error("DBus call to interface %s function GetProperties of path %s failed: %s", + interface().toStdString().c_str(), + objectPath().toStdString().c_str(), + reply.error().message().toStdString().c_str()); + } else { + QVariantMap map = reply.argumentAt<0>(); + foreach (const QString &key, map.keys()) + emit propertyChanged(objectPath(), key, map.value(key)); + } +} + +void NetworkRegistrationWatcher::onPropertyChanged(QString name, QDBusVariant value) +{ + emit propertyChanged(objectPath(), name, value.variant()); +} diff --git a/src/server/networkregistrationwatcher.h b/src/server/networkregistrationwatcher.h new file mode 100644 index 0000000..25db92a --- /dev/null +++ b/src/server/networkregistrationwatcher.h @@ -0,0 +1,30 @@ +#ifndef NETWORKREGISTRATIONRWATCHER_H +#define NETWORKREGISTRATIONRWATCHER_H + +#include +#include +#include + +#include "modemwatcher.h" + +class QDBusInterface; +class QDBusPendingCallWatcher; + +class NetworkRegistrationWatcher : public ModemWatcher +{ + Q_OBJECT +public: + explicit NetworkRegistrationWatcher(const QString objectPath, QObject *parent = 0); + ~NetworkRegistrationWatcher(); + + void getProperties(); + +signals: + void propertyChanged(QString objectPath, QString name, QVariant value); + +private slots: + void onPropertyChanged(QString name, QDBusVariant value); + void getPropertiesAsync(); + void getPropertiesAsyncCallback(QDBusPendingCallWatcher *watcher); +}; +#endif // NETWORKREGISTRATIONRWATCHER_H diff --git a/src/server/networktime.cpp b/src/server/networktime.cpp new file mode 100644 index 0000000..d6d0633 --- /dev/null +++ b/src/server/networktime.cpp @@ -0,0 +1,133 @@ +#include +#include + +#include + +#include "networktime.h" +#include "networktimewatcher.h" + +NetworkTime::NetworkTime(QObject *parent) : + QObject(parent) +{ + foreach (const QString objectPath, m_modemManager.getModems()) + onModemAdded(objectPath); + + QObject::connect(&m_modemManager, SIGNAL(modemAdded(QString)), + this, SLOT(onModemAdded(QString))); + + QObject::connect(&m_modemManager, SIGNAL(modemRemoved(QString)), + this, SLOT(onModemRemoved(QString))); +} + +NetworkTimeInfo NetworkTime::timeInfo() const +{ + return m_networkTimeInfo; +} + +void NetworkTime::queryTimeInfo() +{ + bool querySent = false; + foreach (const QString objectPath, m_watcherMap.keys()) { + if (m_watcherMap.value(objectPath)->interfaceAvailable()) { + m_watcherMap.value(objectPath)->queryNetworkTime(); + querySent = true; + } + } + + if (!querySent) { + m_networkTimeInfo = NetworkTimeInfo(); // Construct a invalid NetworkTimeInfo + emit timeInfoQueryCompleted(m_networkTimeInfo); + } +} + +bool NetworkTime::isValid() const +{ + return m_networkTimeInfo.isValid(); +} + +void NetworkTime::onModemAdded(QString objectPath) +{ + if (!m_watcherMap.contains(objectPath)) { + NetworkTimeWatcher *watcher = new NetworkTimeWatcher(objectPath, this); + QObject::connect(watcher, SIGNAL(networkTimeChanged(QVariantMap)), + this, SLOT(networkTimeChanged(QVariantMap))); + QObject::connect(watcher, SIGNAL(networkTimeQueryCompleted(QVariantMap)), + this, SLOT(networkTimeQueryCompletedSlot(QVariantMap))); + watcher->queryNetworkTime(); + m_watcherMap.insert(objectPath, watcher); + } +} + +void NetworkTime::onModemRemoved(QString objectPath) +{ + if (m_watcherMap.contains(objectPath)) { + NetworkTimeWatcher *watcher = m_watcherMap.value(objectPath); + m_watcherMap.remove(objectPath); + delete watcher; + } +} + +NetworkTimeInfo NetworkTime::parseNetworkTimeInfoFromMap(QVariantMap map) +{ + QVariant tmp; + QDateTime dateTime; + int daylightAdjustment = -1; // -1 means "value not available" + int offsetFromUtc = 0; + qlonglong received = 0; + QString mnc, mcc; + bool ok; + if (!map.isEmpty()) { + tmp = map.value("UTC"); + if (tmp.isValid() && tmp.type() == QVariant::LongLong) { + dateTime.setTimeSpec(Qt::UTC); + qlonglong secs = tmp.toLongLong(&ok); + if (ok) { + dateTime.setMSecsSinceEpoch(secs*1000); + } else { + QDateTime tmp; + dateTime = tmp; + } + } + + tmp = map.value("Received"); + if (tmp.isValid() && tmp.type() == QVariant::LongLong) + received = tmp.toLongLong(&ok); + + tmp = map.value("Timezone"); + if (tmp.isValid() && tmp.type() == QVariant::Int) + offsetFromUtc = tmp.toInt(&ok); + + tmp = map.value("DST"); + if (tmp.isValid() && tmp.type() == QVariant::UInt) { + daylightAdjustment = tmp.toInt(&ok); + if (!ok) + daylightAdjustment = -1; + } + + tmp = map.value("MobileCountryCode"); + if (tmp.isValid() && tmp.type() == QVariant::String) + mcc = tmp.toString(); + + tmp = map.value("MobileNetworkCode"); + if (tmp.isValid() && tmp.type() == QVariant::String) + mnc = tmp.toString(); + } + + return NetworkTimeInfo(dateTime, daylightAdjustment, offsetFromUtc, received, 0, mnc, mcc); +} + +void NetworkTime::networkTimeChanged(QVariantMap map) +{ + m_networkTimeInfo = parseNetworkTimeInfoFromMap(map); + log_debug("time: %s", + m_networkTimeInfo.toString().toStdString().c_str()); + emit timeInfoChanged(m_networkTimeInfo); +} + +void NetworkTime::networkTimeQueryCompletedSlot(QVariantMap map) +{ + m_networkTimeInfo = parseNetworkTimeInfoFromMap(map); + log_debug("time: %s", + m_networkTimeInfo.toString().toStdString().c_str()); + emit timeInfoQueryCompleted(m_networkTimeInfo); +} diff --git a/src/server/networktime.h b/src/server/networktime.h new file mode 100644 index 0000000..877fa95 --- /dev/null +++ b/src/server/networktime.h @@ -0,0 +1,41 @@ +#ifndef NETWORKTIME_H +#define NETWORKTIME_H + +#include +#include +#include + +#include "networktimeinfo.h" +#include "ofonomodemmanager.h" + +class QDBusPendingCallWatcher; +class NetworkTimeWatcher; + +// See http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libcellular-qt/classCellular_1_1NetworkTime.html +class NetworkTime : public QObject +{ + Q_OBJECT + +public: + explicit NetworkTime (QObject *parent=0); + NetworkTimeInfo timeInfo() const; + void queryTimeInfo(); + bool isValid() const; + +signals: + void timeInfoChanged(const NetworkTimeInfo &timeInfo); + void timeInfoQueryCompleted(const NetworkTimeInfo &timeInfo); + +private: + NetworkTimeInfo m_networkTimeInfo; + QMap m_watcherMap; + NetworkTimeInfo parseNetworkTimeInfoFromMap(QVariantMap map); + OfonoModemManager m_modemManager; + +private slots: + void onModemAdded(QString objectPath); + void onModemRemoved(QString objectPath); + void networkTimeChanged(QVariantMap map); + void networkTimeQueryCompletedSlot(QVariantMap map); +}; +#endif // NETWORKTIME_H diff --git a/src/server/networktimeinfo.cpp b/src/server/networktimeinfo.cpp new file mode 100644 index 0000000..77dc102 --- /dev/null +++ b/src/server/networktimeinfo.cpp @@ -0,0 +1,88 @@ +#include "networktimeinfo.h" + +NetworkTimeInfo::NetworkTimeInfo(const QDateTime &dateTime, + const int daylightAdjustment, + const int offsetFromUtc, + const qlonglong timestampSeconds, + const qlonglong timestampNanoSeconds, + const QString &mnc, + const QString &mcc) + : m_dateTime(dateTime), m_daylightAdjustment(daylightAdjustment), + m_offsetFromUtc(offsetFromUtc), + m_timestampSeconds(timestampSeconds), + m_timestampNanoSeconds(timestampNanoSeconds), + m_mnc(mnc), m_mcc(mcc) +{ +} + +NetworkTimeInfo::NetworkTimeInfo(const NetworkTimeInfo &other) +{ + m_dateTime = other.dateTime(); + m_daylightAdjustment = other.daylightAdjustment(); + m_offsetFromUtc = other.offsetFromUtc(); + m_timestampSeconds = other.timestamp()->tv_sec; + m_timestampNanoSeconds = other.timestamp()->tv_nsec; + m_mnc = other.mnc(); + m_mcc = other.mcc(); +} + +NetworkTimeInfo::NetworkTimeInfo() +{ +} + +NetworkTimeInfo::~NetworkTimeInfo() +{ +} + +QDateTime NetworkTimeInfo::dateTime() const +{ + return m_dateTime; +} + +int NetworkTimeInfo::offsetFromUtc() const +{ + return m_offsetFromUtc; +} + +int NetworkTimeInfo::daylightAdjustment() const +{ + return m_daylightAdjustment; +} + +timespec* NetworkTimeInfo::timestamp() const +{ + struct timespec *ts = new timespec; + ts->tv_sec = m_timestampSeconds; + ts->tv_nsec = m_timestampNanoSeconds; + return ts; +} + +QString NetworkTimeInfo::mnc() const +{ + return m_mnc; +} + +QString NetworkTimeInfo::mcc() const +{ + return m_mcc; +} + +bool NetworkTimeInfo::isValid() const +{ + return m_dateTime.isValid(); +} + +QString NetworkTimeInfo::toString() const +{ + if (!m_dateTime.isValid()) + return QString("Invalid"); + + return QString("%1, UTC offset: %2, DST: %3, MNC: %4, MCC: %5, Received: %6.%7") + .arg(m_dateTime.toString()) + .arg(m_offsetFromUtc) + .arg(m_daylightAdjustment) + .arg(m_mnc) + .arg(m_mcc) + .arg(m_timestampSeconds) + .arg(m_timestampNanoSeconds); +} diff --git a/src/server/networktimeinfo.h b/src/server/networktimeinfo.h new file mode 100644 index 0000000..f0769d7 --- /dev/null +++ b/src/server/networktimeinfo.h @@ -0,0 +1,37 @@ +#ifndef NETWORKTIMEINFO_H +#define NETWORKTIMEINFO_H + +#include +#include +#include + +// See http://harmattan-dev.nokia.com/docs/platform-api-reference/xml/daily-docs/libcellular-qt/classCellular_1_1NetworkTimeInfo.html +class NetworkTimeInfo +{ +public: + NetworkTimeInfo(const QDateTime &dateTime, const int daylightAdjustment, + const int offsetFromUtc, const qlonglong timestampSeconds, + const qlonglong timestampNanoSeconds, const QString &mnc, const QString &mcc); + NetworkTimeInfo(const NetworkTimeInfo &other); + NetworkTimeInfo(); + ~NetworkTimeInfo(); + + QDateTime dateTime() const; + int offsetFromUtc() const; + int daylightAdjustment() const; + struct timespec* timestamp() const; + QString mnc() const; + QString mcc() const; + bool isValid() const; + QString toString() const; + +private: + QDateTime m_dateTime; + int m_daylightAdjustment; + int m_offsetFromUtc; + qlonglong m_timestampSeconds; + qlonglong m_timestampNanoSeconds; + QString m_mnc; + QString m_mcc; +}; +#endif // NETWORKTIMEINFO_H diff --git a/src/server/networktimewatcher.cpp b/src/server/networktimewatcher.cpp new file mode 100644 index 0000000..02a3ab1 --- /dev/null +++ b/src/server/networktimewatcher.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +#include + +#include "networktimewatcher.h" + +NetworkTimeWatcher::NetworkTimeWatcher(const QString path, QObject *parent) : + ModemWatcher(path, "org.ofono.NetworkTime", parent) +{ + QDBusConnection::systemBus().connect("org.ofono", objectPath(), + interface(), "NetworkTimeChanged", + this, SLOT(onNetworkTimeChanged(QVariantMap))); + + QObject::connect(this, SIGNAL(interfaceAvailableChanged(bool)), this, SLOT(queryNetworkTime())); +} + +NetworkTimeWatcher::~NetworkTimeWatcher() +{ + QDBusConnection::systemBus().disconnect("org.ofono", objectPath(), + interface(), "NetworkTimeChanged", + this, SLOT(onNetworkTimeChanged(QVariantMap))); +} + +void NetworkTimeWatcher::queryNetworkTime() +{ + if (!interfaceAvailable()) + return; + + QDBusInterface dbusInterface("org.ofono", objectPath(), interface(), QDBusConnection::systemBus()); + if (dbusInterface.isValid()) { + QDBusPendingCall async = dbusInterface.asyncCall("GetNetworkTime"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(queryNetworkTimeCallback(QDBusPendingCallWatcher*))); + } else { + log_error("Dbus interface %s of path %s is invalid.", + interface().toStdString().c_str(), + objectPath().toStdString().c_str()); + } +} + +void NetworkTimeWatcher::queryNetworkTimeCallback(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply reply = *watcher; + if (reply.error().isValid()) { + log_error("DBus call to interface %s function GetNetworkTime of path %s failed: %s", + interface().toStdString().c_str(), + objectPath().toStdString().c_str(), + reply.error().message().toStdString().c_str()); + } else { + QVariantMap map = reply.argumentAt<0>(); + emit networkTimeQueryCompleted(map); + } +} + +void NetworkTimeWatcher::onNetworkTimeChanged(QVariantMap map) +{ + emit networkTimeChanged(map); +} + diff --git a/src/server/networktimewatcher.h b/src/server/networktimewatcher.h new file mode 100644 index 0000000..580e5dd --- /dev/null +++ b/src/server/networktimewatcher.h @@ -0,0 +1,32 @@ +#ifndef NETWORKTIMEWATCHER_H +#define NETWORKTIMEWATCHER_H + +#include +#include +#include + +#include "modemwatcher.h" + +class QDBusInterface; +class QDBusPendingCallWatcher; + +class NetworkTimeWatcher : public ModemWatcher +{ + Q_OBJECT + +public: + explicit NetworkTimeWatcher(const QString objectPath, QObject *parent = 0); + ~NetworkTimeWatcher(); + +public slots: + void queryNetworkTime(); + +signals: + void networkTimeChanged(QVariantMap map); + void networkTimeQueryCompleted(QVariantMap map); + +private slots: + void queryNetworkTimeCallback(QDBusPendingCallWatcher *watcher); + void onNetworkTimeChanged(QVariantMap map); +}; +#endif // NETWORKTIMEWATCHER_H diff --git a/src/server/ofonomodemmanager.cpp b/src/server/ofonomodemmanager.cpp new file mode 100644 index 0000000..d9c5392 --- /dev/null +++ b/src/server/ofonomodemmanager.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "ofonomodemmanager.h" +#include "modemwatcher.h" + +struct OfonoModemProperties +{ + QDBusObjectPath name; + QMap dict; +}; + +typedef QList OfonoModemList; + +QDBusArgument &operator<<(QDBusArgument &argument, const OfonoModemProperties &modemProperties) +{ + argument.beginStructure(); + argument << modemProperties.name << modemProperties.dict; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, OfonoModemProperties &modemProperties) +{ + argument.beginStructure(); + argument >> modemProperties.name >> modemProperties.dict; + argument.endStructure(); + return argument; +} + +Q_DECLARE_METATYPE(OfonoModemProperties) +Q_DECLARE_METATYPE(OfonoModemList) + +OfonoModemManager::OfonoModemManager(QObject *parent) : + QObject(parent) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + QDBusConnection::systemBus().connect("org.ofono", "/", "org.ofono.Manager", "ModemAdded", + this, SLOT(onModemAdded(QDBusObjectPath, QVariantMap))); + QDBusConnection::systemBus().connect("org.ofono", "/", "org.ofono.Manager", "ModemRemoved", + this, SLOT(onModemRemoved(QDBusObjectPath))); + + QDBusMessage request = QDBusMessage::createMethodCall("org.ofono", + "/", "org.ofono.Manager", + "GetModems"); + + QDBusReply reply = QDBusConnection::systemBus().call(request); + if (reply.error().isValid()) { + log_error("DBus call to interface org.ofono.Manager function GetModems of path / failed: %s", + reply.error().message().toStdString().c_str()); + } else { + OfonoModemList list = reply; + for (int i = 0; i < list.count(); i++) + addModem(list.at(i).name.path()); + } +} + +OfonoModemManager::~OfonoModemManager() +{ + QDBusConnection::systemBus().disconnect("org.ofono", "/", "org.ofono.Manager", "ModemAdded", + this, SLOT(onModemAdded(QDBusObjectPath, QVariantMap))); + QDBusConnection::systemBus().disconnect("org.ofono", "/", "org.ofono.Manager", "ModemRemoved", + this, SLOT(onModemRemoved(QDBusObjectPath))); +} + +bool OfonoModemManager::addModem(QString objectPath) +{ + if (!m_modemList.contains(objectPath)) { + m_modemList.append(objectPath); + return true; + } + return false; +} + +QStringList OfonoModemManager::getModems() +{ + return m_modemList; +} + +void OfonoModemManager::onModemAdded(QDBusObjectPath objectPath, QVariantMap map) +{ + Q_UNUSED(map) + QString path = objectPath.path(); + if (addModem(path)) + emit modemAdded(path); +} + +void OfonoModemManager::onModemRemoved(QDBusObjectPath objectPath) +{ + QString path = objectPath.path(); + if (m_modemList.contains(path)) { + m_modemList.removeAll(path); + emit modemRemoved(path); + } +} diff --git a/src/server/ofonomodemmanager.h b/src/server/ofonomodemmanager.h new file mode 100644 index 0000000..368e6e6 --- /dev/null +++ b/src/server/ofonomodemmanager.h @@ -0,0 +1,34 @@ +#ifndef OFONOMODEMMANAGER_H +#define OFONOMODEMMANAGER_H + +#include +#include +#include +#include + +class ModemWatcher; + +class OfonoModemManager : public QObject +{ + Q_OBJECT + +public: + explicit OfonoModemManager(QObject *parent = 0); + ~OfonoModemManager(); + + QStringList getModems(); + +signals: + void modemAdded(QString objectPath); + void modemRemoved(QString objectPath); + +private slots: + void onModemAdded(QDBusObjectPath objectPath, QVariantMap map); + void onModemRemoved(QDBusObjectPath objectPath); + +private: + QStringList m_modemList; + bool addModem(QString objectPath); +}; + +#endif // OFONOMODEMMANAGER_H