pax_global_header00006660000000000000000000000064145763055570014533gustar00rootroot0000000000000052 comment=1893185f2124ef5487fc684f9e69237b8551f4c4 libqofonoext-1.0.32/000077500000000000000000000000001457630555700143275ustar00rootroot00000000000000libqofonoext-1.0.32/.gitignore000066400000000000000000000003001457630555700163100ustar00rootroot00000000000000*~ build .DS_Store *.pro.user .qmake.stash Makefile plugin/Makefile plugin/libqofonoextdeclarative*.so* src/Makefile src/libqofonoext*.prl src/libqofonoext*.so* src/pkgconfig/ moc_* *.o *.moc libqofonoext-1.0.32/LICENSE.LGPL000066400000000000000000000011071457630555700160700ustar00rootroot00000000000000Copyright (C) 2015-2023 Slava Monich Copyright (C) 2015-2022 Jolla Ltd. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. libqofonoext-1.0.32/README000066400000000000000000000001671457630555700152130ustar00rootroot00000000000000qofono-ext ========== A library for accessing Sailfish OS specific ofono extensions, and a declarative plugin for it. libqofonoext-1.0.32/libqofonoext.pro000066400000000000000000000002261457630555700175620ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += src plugin OTHER_FILES += rpm/libqofonoext.spec LICENSE.LGPL README src.target = src-target plugin.depends = src-target libqofonoext-1.0.32/plugin/000077500000000000000000000000001457630555700156255ustar00rootroot00000000000000libqofonoext-1.0.32/plugin/plugin.pro000066400000000000000000000015151457630555700176470ustar00rootroot00000000000000TARGET=qofonoextdeclarative TEMPLATE = lib CONFIG += plugin link_pkgconfig PKGCONFIG += qofono-qt$${QT_MAJOR_VERSION} QMAKE_CXXFLAGS += -Wno-unused-parameter -Wno-psabi QT_VERSION=$$[QT_VERSION] QT += qml dbus QT -= gui LIBS += -L../src -lqofonoext INCLUDEPATH += ../src SOURCES = \ qofonoextdeclarativeplugin.cpp \ qofonoextmodemlistmodel.cpp \ qofonoextsimlistmodel.cpp HEADERS = \ qofonoextdeclarativeplugin.h \ qofonoextmodemlistmodel.h \ qofonoextsimlistmodel.h OTHER_FILES += qmldir plugins.qmltypes target.path = $$[QT_INSTALL_QML]/org/nemomobile/ofono qmldir.path = $$[QT_INSTALL_QML]/org/nemomobile/ofono qmldir.files += qmldir plugins.qmltypes INSTALLS += target qmldir qmltypes.commands = qmlplugindump -nonrelocatable org.nemomobile.ofono 1.0 > $$PWD/plugins.qmltypes QMAKE_EXTRA_TARGETS += qmltypes libqofonoext-1.0.32/plugin/plugins.qmltypes000066400000000000000000000243731457630555700211170ustar00rootroot00000000000000import QtQuick.tooling 1.2 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. // // This file was auto-generated by: // 'qmlplugindump -nonrelocatable org.nemomobile.ofono 1.0' Module { dependencies: ["QtQuick 2.0"] Component { name: "QOfonoExtCell" prototype: "QObject" exports: ["org.nemomobile.ofono/OfonoExtCell 1.0"] exportMetaObjectRevisions: [0] Enum { name: "Type" values: { "Unknown": 0, "GSM": 1, "WCDMA": 2, "LTE": 3, "NR": 4, "UNKNOWN": 0 } } Enum { name: "Constants" values: { "InvalidValue": 2147483647 } } Property { name: "path"; type: "string" } Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "type"; type: "Type"; isReadonly: true } Property { name: "registered"; type: "bool"; isReadonly: true } Property { name: "mcc"; type: "int"; isReadonly: true } Property { name: "mnc"; type: "int"; isReadonly: true } Property { name: "signalStrength"; type: "int"; isReadonly: true } Property { name: "lac"; type: "int"; isReadonly: true } Property { name: "cid"; type: "int"; isReadonly: true } Property { name: "arfcn"; type: "int"; isReadonly: true } Property { name: "bsic"; type: "int"; isReadonly: true } Property { name: "bitErrorRate"; type: "int"; isReadonly: true } Property { name: "psc"; type: "int"; isReadonly: true } Property { name: "uarfcn"; type: "int"; isReadonly: true } Property { name: "ci"; type: "int"; isReadonly: true } Property { name: "pci"; type: "int"; isReadonly: true } Property { name: "tac"; type: "int"; isReadonly: true } Property { name: "earfcn"; type: "int"; isReadonly: true } Property { name: "rsrp"; type: "int"; isReadonly: true } Property { name: "rsrq"; type: "int"; isReadonly: true } Property { name: "rssnr"; type: "int"; isReadonly: true } Property { name: "cqi"; type: "int"; isReadonly: true } Property { name: "timingAdvance"; type: "int"; isReadonly: true } Property { name: "nci"; type: "string"; isReadonly: true } Property { name: "nrarfcn"; type: "int"; isReadonly: true } Property { name: "ssRsrp"; type: "int"; isReadonly: true } Property { name: "ssRsrq"; type: "int"; isReadonly: true } Property { name: "ssSinr"; type: "int"; isReadonly: true } Property { name: "csiRsrp"; type: "int"; isReadonly: true } Property { name: "csiRsrq"; type: "int"; isReadonly: true } Property { name: "csiSinr"; type: "int"; isReadonly: true } Property { name: "signalLevelDbm"; type: "int"; isReadonly: true } Signal { name: "propertyChanged" Parameter { name: "name"; type: "string" } Parameter { name: "value"; type: "int" } } Signal { name: "removed" } } Component { name: "QOfonoExtCellInfo" prototype: "QObject" exports: ["org.nemomobile.ofono/OfonoExtCellInfo 1.0"] exportMetaObjectRevisions: [0] Property { name: "modemPath"; type: "string" } Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "cells"; type: "QStringList"; isReadonly: true } Signal { name: "cellsAdded" Parameter { name: "cells"; type: "QStringList" } } Signal { name: "cellsRemoved" Parameter { name: "cells"; type: "QStringList" } } } Component { name: "QOfonoExtModemListModel" prototype: "QAbstractListModel" exports: ["org.nemomobile.ofono/OfonoModemListModel 1.0"] exportMetaObjectRevisions: [0] Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "count"; type: "int"; isReadonly: true } Signal { name: "validChanged" Parameter { name: "aValid"; type: "bool" } } Signal { name: "countChanged" Parameter { name: "aCount"; type: "int" } } } Component { name: "QOfonoExtModemManager" prototype: "QObject" exports: ["org.nemomobile.ofono/OfonoModemManager 1.0"] exportMetaObjectRevisions: [0] Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "interfaceVersion"; type: "int"; isReadonly: true } Property { name: "availableModems"; type: "QStringList"; isReadonly: true } Property { name: "enabledModems"; type: "QStringList" } Property { name: "defaultDataModem"; type: "string"; isReadonly: true } Property { name: "defaultVoiceModem"; type: "string"; isReadonly: true } Property { name: "defaultDataSim"; type: "string" } Property { name: "defaultVoiceSim"; type: "string" } Property { name: "presentSims"; type: "QList"; isReadonly: true } Property { name: "imeiCodes"; type: "QStringList"; isReadonly: true } Property { name: "imeisvCodes"; type: "QStringList"; isReadonly: true } Property { name: "mmsSim"; type: "string"; isReadonly: true } Property { name: "mmsModem"; type: "string"; isReadonly: true } Property { name: "ready"; type: "bool"; isReadonly: true } Property { name: "presentSimCount"; type: "int"; isReadonly: true } Property { name: "activeSimCount"; type: "int"; isReadonly: true } Property { name: "errorCount"; type: "int"; isReadonly: true } Signal { name: "validChanged" Parameter { name: "value"; type: "bool" } } Signal { name: "interfaceVersionChanged" Parameter { name: "value"; type: "int" } } Signal { name: "availableModemsChanged" Parameter { name: "value"; type: "QStringList" } } Signal { name: "enabledModemsChanged" Parameter { name: "value"; type: "QStringList" } } Signal { name: "defaultVoiceModemChanged" Parameter { name: "value"; type: "string" } } Signal { name: "defaultDataModemChanged" Parameter { name: "value"; type: "string" } } Signal { name: "defaultVoiceSimChanged" Parameter { name: "value"; type: "string" } } Signal { name: "defaultDataSimChanged" Parameter { name: "value"; type: "string" } } Signal { name: "presentSimsChanged" Parameter { name: "value"; type: "QList" } } Signal { name: "presentSimChanged" Parameter { name: "index"; type: "int" } Parameter { name: "present"; type: "bool" } } Signal { name: "presentSimCountChanged" Parameter { name: "value"; type: "int" } } Signal { name: "activeSimCountChanged" Parameter { name: "value"; type: "int" } } Signal { name: "imeiCodesChanged" Parameter { name: "value"; type: "QStringList" } } Signal { name: "imeisvCodesChanged" Parameter { name: "value"; type: "QStringList" } } Signal { name: "mmsSimChanged" Parameter { name: "value"; type: "string" } } Signal { name: "mmsModemChanged" Parameter { name: "value"; type: "string" } } Signal { name: "readyChanged" Parameter { name: "value"; type: "bool" } } Signal { name: "errorCountChanged" Parameter { name: "value"; type: "int" } } Signal { name: "modemError" Parameter { name: "modemPath"; type: "string" } Parameter { name: "errorId"; type: "string" } Parameter { name: "errorMessage"; type: "string" } } Method { name: "imeiAt" type: "string" Parameter { name: "aIndex"; type: "int" } } Method { name: "imeisvAt" type: "string" Parameter { name: "aIndex"; type: "int" } } Method { name: "simPresentAt" type: "bool" Parameter { name: "aIndex"; type: "int" } } } Component { name: "QOfonoExtSimInfo" prototype: "QObject" exports: ["org.nemomobile.ofono/OfonoSimInfo 1.0"] exportMetaObjectRevisions: [0] Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "modemPath"; type: "string" } Property { name: "cardIdentifier"; type: "string"; isReadonly: true } Property { name: "subscriberIdentity"; type: "string"; isReadonly: true } Property { name: "serviceProviderName"; type: "string"; isReadonly: true } Signal { name: "validChanged" Parameter { name: "value"; type: "bool" } } Signal { name: "modemPathChanged" Parameter { name: "value"; type: "string" } } Signal { name: "cardIdentifierChanged" Parameter { name: "value"; type: "string" } } Signal { name: "subscriberIdentityChanged" Parameter { name: "value"; type: "string" } } Signal { name: "serviceProviderNameChanged" Parameter { name: "value"; type: "string" } } } Component { name: "QOfonoExtSimListModel" prototype: "QAbstractListModel" exports: ["org.nemomobile.ofono/OfonoExtSimListModel 1.0"] exportMetaObjectRevisions: [0] Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "count"; type: "int"; isReadonly: true } Signal { name: "simAdded" Parameter { name: "sim"; type: "QOfonoExtSimInfo"; isPointer: true } } Signal { name: "simRemoved" Parameter { name: "path"; type: "string" } } } } libqofonoext-1.0.32/plugin/qmldir000066400000000000000000000001221457630555700170330ustar00rootroot00000000000000module org.nemomobile.ofono plugin qofonoextdeclarative typeinfo plugins.qmltypes libqofonoext-1.0.32/plugin/qofonoextdeclarativeplugin.cpp000066400000000000000000000033761457630555700240070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextdeclarativeplugin.h" #include "qofonoextmodemlistmodel.h" #include "qofonoextmodemmanager.h" #include "qofonoextsiminfo.h" #include "qofonoextsimlistmodel.h" #include "qofonoextmodemlistmodel.h" #include "qofonoextcellinfo.h" #include "qofonoextcell.h" #include void QOfonoExtDeclarativePlugin::registerTypes(const char* aUri, int aMajor, int aMinor) { Q_ASSERT(QLatin1String(aUri) == "org.nemomobile.ofono"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoModemManager"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoModemListModel"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoSimInfo"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoExtSimListModel"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoExtCellInfo"); qmlRegisterType(aUri, aMajor, aMinor, "OfonoExtCell"); } void QOfonoExtDeclarativePlugin::registerTypes(const char* aUri) { registerTypes(aUri, 1, 0); } libqofonoext-1.0.32/plugin/qofonoextdeclarativeplugin.h000066400000000000000000000022531457630555700234450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTDECLARATIVEPLUGIN_H #define QOFONOEXTDECLARATIVEPLUGIN_H #include "qofonoext_types.h" #include class QOFONOEXT_EXPORT QOfonoExtDeclarativePlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char* aUri); static void registerTypes(const char* aUri, int aMajor, int aMinor); }; #endif // QOFONOEXTDECLARATIVEPLUGIN_H libqofonoext-1.0.32/plugin/qofonoextmodemlistmodel.cpp000066400000000000000000000171351457630555700233210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextmodemlistmodel.h" QOfonoExtModemListModel::QOfonoExtModemListModel(QObject* aParent) : QAbstractListModel(aParent), iModemManager(QOfonoExtModemManager::instance()), iAvailableModems(iModemManager->availableModems()), iEnabledModems(iModemManager->enabledModems()), iDefaultVoiceModem(iModemManager->defaultVoiceModem()), iDefaultDataModem(iModemManager->defaultDataModem()) { connect(iModemManager.data(), SIGNAL(validChanged(bool)), SLOT(onValidChanged(bool))); connect(iModemManager.data(), SIGNAL(availableModemsChanged(QStringList)), SLOT(onAvailableModemsChanged(QStringList))); connect(iModemManager.data(), SIGNAL(enabledModemsChanged(QStringList)), SLOT(onEnabledModemsChanged(QStringList))); connect(iModemManager.data(), SIGNAL(defaultDataModemChanged(QString)), SLOT(onDefaultDataModemChanged(QString))); connect(iModemManager.data(), SIGNAL(defaultVoiceModemChanged(QString)), SLOT(onDefaultVoiceModemChanged(QString))); connect(iModemManager.data(), SIGNAL(presentSimChanged(int,bool)), SLOT(onPresentSimChanged(int,bool))); connect(iModemManager.data(), SIGNAL(imeiCodesChanged(QStringList)), SLOT(onImeiCodesChanged(QStringList))); connect(iModemManager.data(), SIGNAL(imeisvCodesChanged(QStringList)), SLOT(onImeisvCodesChanged(QStringList))); } bool QOfonoExtModemListModel::valid() const { return iModemManager->valid(); } int QOfonoExtModemListModel::count() const { return iAvailableModems.count(); } QHash QOfonoExtModemListModel::roleNames() const { QHash roles; roles[PathRole] = "path"; roles[EnabledRole] = "enabled"; roles[DefaultDataRole] = "defaultForData"; roles[DefaultVoiceRole] = "defaultForVoice"; roles[SimPresentRole] = "simPresent"; roles[IMEIRole] = "imei"; roles[IMEISVRole] = "imeisv"; return roles; } int QOfonoExtModemListModel::rowCount(const QModelIndex& aParent) const { return iAvailableModems.count(); } QVariant QOfonoExtModemListModel::data(const QModelIndex& aIndex, int aRole) const { const int row = aIndex.row(); if (row >= 0 && row < iAvailableModems.count()) { switch (aRole) { case PathRole: return iAvailableModems.at(row); case EnabledRole: return iEnabledModems.contains(iAvailableModems.at(row)); case DefaultDataRole: return iAvailableModems.indexOf(iDefaultDataModem) == row; case DefaultVoiceRole: return iAvailableModems.indexOf(iDefaultVoiceModem) == row; case SimPresentRole: return iModemManager->simPresentAt(row); case IMEIRole: return iModemManager->imeiAt(row); case IMEISVRole: return iModemManager->imeisvAt(row); } } qWarning() << aIndex << aRole; return QVariant(); } bool QOfonoExtModemListModel::setData(const QModelIndex& aIndex, const QVariant& aValue, int aRole) { const int row = aIndex.row(); if (row >= 0 && row < iAvailableModems.count() && aRole == EnabledRole) { const bool enabled = aValue.toBool(); const QString& path(iAvailableModems.at(row)); const int index = iEnabledModems.indexOf(path); if (enabled != (index >= 0)) { QStringList enabledModems = iEnabledModems; if (enabled) { enabledModems.append(path); } else { enabledModems.removeAt(index); } iModemManager->setEnabledModems(enabledModems); } return true; } return false; } void QOfonoExtModemListModel::onValidChanged(bool aValid) { if (aValid) { beginResetModel(); endResetModel(); } Q_EMIT validChanged(aValid); } void QOfonoExtModemListModel::onAvailableModemsChanged(QStringList aModems) { const bool countHasChanged = iAvailableModems.count() != aModems.count(); beginResetModel(); iAvailableModems = aModems; endResetModel(); if (countHasChanged) { Q_EMIT countChanged(iAvailableModems.count()); } } void QOfonoExtModemListModel::onEnabledModemsChanged(QStringList aModems) { if (iEnabledModems != aModems) { QStringList prevModems = iEnabledModems; iEnabledModems = aModems; const int n = iAvailableModems.count(); QVector role; role.append(EnabledRole); for (int i=0; i role; role.append(SimPresentRole); QModelIndex index(createIndex(aIndex, 0)); Q_EMIT dataChanged(index, index, role); } void QOfonoExtModemListModel::defaultModemChanged(Role aRole, int aPrevRow, int aNewRow) { if (aPrevRow != aNewRow) { QVector role; role.append(aRole); if (aPrevRow >= 0) { QModelIndex index(createIndex(aPrevRow, 0)); Q_EMIT dataChanged(index, index, role); } if (aNewRow >= 0) { QModelIndex index(createIndex(aNewRow, 0)); Q_EMIT dataChanged(index, index, role); } } } void QOfonoExtModemListModel::onImeiCodesChanged(QStringList aList) { QStringList prev = iImeiList; iImeiList = aList; roleChanged(IMEIRole, prev, aList); } void QOfonoExtModemListModel::onImeisvCodesChanged(QStringList aList) { QStringList prev = iImeisvList; iImeisvList = aList; roleChanged(IMEISVRole, prev, aList); } void QOfonoExtModemListModel::roleChanged(Role aRole, QStringList aPrevList, QStringList aNewList) { // This is slightly paranoid... All these 3 counts should be the same const int n1 = iAvailableModems.count(); const int n2 = aPrevList.count(); const int n3 = aNewList.count(); const int n = qMin(n1, qMin(n2, n3)); QVector role; role.append(aRole); for (int i=0; i ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTMODEMLISTMODEL_H #define QOFONOEXTMODEMLISTMODEL_H #include "qofonoextmodemmanager.h" #include class QOfonoExtModemListModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) public: enum Role { PathRole = Qt::UserRole, EnabledRole, DefaultDataRole, DefaultVoiceRole, SimPresentRole, IMEIRole, IMEISVRole }; explicit QOfonoExtModemListModel(QObject* aParent = NULL); bool valid() const; int count() const; QHash roleNames() const; int rowCount(const QModelIndex& aParent) const; QVariant data(const QModelIndex& aIndex, int aRole) const; bool setData(const QModelIndex& aIndex, const QVariant& aValue, int aRole); Q_SIGNALS: void validChanged(bool aValid); void countChanged(int aCount); private Q_SLOTS: void onValidChanged(bool aValid); void onAvailableModemsChanged(QStringList aModems); void onEnabledModemsChanged(QStringList aModems); void onDefaultDataModemChanged(QString aModemPath); void onDefaultVoiceModemChanged(QString aModemPath); void onPresentSimChanged(int aIndex, bool aPresent); void onImeiCodesChanged(QStringList aList); void onImeisvCodesChanged(QStringList aList); private: void defaultModemChanged(Role aRole, int aPrevRow, int aNewRow); void roleChanged(Role aRole, QStringList aPrevList, QStringList aNewList); private: QSharedPointer iModemManager; QStringList iAvailableModems; QStringList iEnabledModems; QString iDefaultVoiceModem; QString iDefaultDataModem; QStringList iImeiList; QStringList iImeisvList; }; #endif // QOFONOEXTMODEMLISTMODEL_H libqofonoext-1.0.32/plugin/qofonoextsimlistmodel.cpp000066400000000000000000000274241457630555700230120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextsimlistmodel.h" #include class QOfonoExtSimListModel::SimData : public QObject { public: friend class QOfonoExtSimListModel; Q_OBJECT SimData(QOfonoExtSimListModel* aParent, QSharedPointer aModemManager, QOfonoSimManager::SharedPointer aSimManager, int aIndex = -1); private Q_SLOTS: void onValidChanged(); void onSubscriberIdentityChanged(); void onMobileCountryCodeChanged(); void onMobileNetworkCodeChanged(); void onServiceProviderNameChanged(); void onSubscriberNumbersChanged(); void onServiceNumbersChanged(); void onPinRequiredChanged(); void onLockedPinsChanged(); void onCardIdentifierChanged(); void onPreferredLanguagesChanged(); void onPinRetriesChanged(); void onFixedDialingChanged(); void onBarredDialingChanged(); private: void propertyChanged(Role role); bool isValid() const; int slotNumber() const; public: QOfonoExtSimListModel* iParent; QSharedPointer iModemManager; QOfonoSimManager::SharedPointer iSim; QOfonoExtSimInfo* iCache; int iIndex; int iSlot; bool iValid; }; QOfonoExtSimListModel::SimData::SimData(QOfonoExtSimListModel* aParent, QSharedPointer aModemManager, QOfonoSimManager::SharedPointer aSimManager, int aIndex) : QObject(aParent), iParent(aParent), iModemManager(aModemManager), iSim(aSimManager), iCache(new QOfonoExtSimInfo(this)), iIndex(aIndex) { iSlot = slotNumber(); iValid = isValid(); QOfonoSimManager* sim = iSim.data(); QQmlEngine::setObjectOwnership(iCache, QQmlEngine::CppOwnership); iCache->setModemPath(sim->modemPath()); connect(iCache, SIGNAL(validChanged(bool)), SLOT(onValidChanged())); connect(iCache, SIGNAL(subscriberIdentityChanged(QString)), SLOT(onSubscriberIdentityChanged())); connect(iCache, SIGNAL(serviceProviderNameChanged(QString)), SLOT(onServiceProviderNameChanged())); connect(iModemManager.data(), SIGNAL(validChanged(bool)), SLOT(onValidChanged())); connect(sim, SIGNAL(mobileCountryCodeChanged(QString)), SLOT(onMobileCountryCodeChanged())); connect(sim, SIGNAL(mobileNetworkCodeChanged(QString)), SLOT(onMobileNetworkCodeChanged())); connect(sim, SIGNAL(subscriberNumbersChanged(QStringList)), SLOT(onSubscriberNumbersChanged())); connect(sim, SIGNAL(serviceNumbersChanged(QVariantMap)), SLOT(onServiceNumbersChanged())); connect(sim, SIGNAL(pinRequiredChanged(int)), SLOT(onPinRequiredChanged())); connect(sim, SIGNAL(lockedPinsChanged(QVariantList)), SLOT(onLockedPinsChanged())); connect(sim, SIGNAL(cardIdentifierChanged(QString)), SLOT(onCardIdentifierChanged())); connect(sim, SIGNAL(preferredLanguagesChanged(QStringList)), SLOT(onPreferredLanguagesChanged())); connect(sim, SIGNAL(pinRetriesChanged(QVariantMap)), SLOT(onPinRetriesChanged())); connect(sim, SIGNAL(fixedDialingChanged(bool)), SLOT(onFixedDialingChanged())); connect(sim, SIGNAL(barredDialingChanged(bool)), SLOT(onBarredDialingChanged())); } void QOfonoExtSimListModel::SimData::propertyChanged(Role role) { if (iIndex >= 0) { QModelIndex modelIndex = iParent->index(iIndex); QVector roles; roles.append(role); Q_EMIT iParent->dataChanged(modelIndex, modelIndex, roles); } } bool QOfonoExtSimListModel::SimData::isValid() const { // QOfonoSimWatcher guarantees that QOfonoSimManager is valid return iModemManager->valid() && iCache->valid(); } int QOfonoExtSimListModel::SimData::slotNumber() const { // The first slot is 1, second slot 2 and so on return iModemManager->availableModems().indexOf(iSim->modemPath()) + 1; } void QOfonoExtSimListModel::SimData::onValidChanged() { const bool valid = isValid(); if (valid) { // Once set, slot number doesn't change const int slot = slotNumber(); if (slot && iSlot != slot) { iSlot = slot; propertyChanged(SlotRole); } } if (iValid != valid) { iValid = valid; propertyChanged(ValidRole); iParent->checkValid(); } } void QOfonoExtSimListModel::SimData::onSubscriberIdentityChanged() { propertyChanged(SubscriberIdentityRole); } void QOfonoExtSimListModel::SimData::onMobileCountryCodeChanged() { propertyChanged(MobileCountryCodeRole); } void QOfonoExtSimListModel::SimData::onMobileNetworkCodeChanged() { propertyChanged(MobileNetworkCodeRole); } void QOfonoExtSimListModel::SimData::onServiceProviderNameChanged() { propertyChanged(ServiceProviderNameRole); } void QOfonoExtSimListModel::SimData::onSubscriberNumbersChanged() { propertyChanged(SubscriberNumbersRole); } void QOfonoExtSimListModel::SimData::onServiceNumbersChanged() { propertyChanged(ServiceNumbersRole); } void QOfonoExtSimListModel::SimData::onPinRequiredChanged() { propertyChanged(PinRequiredRole); } void QOfonoExtSimListModel::SimData::onLockedPinsChanged() { propertyChanged(LockedPinsRole); } void QOfonoExtSimListModel::SimData::onCardIdentifierChanged() { propertyChanged(CardIdentifierRole); } void QOfonoExtSimListModel::SimData::onPreferredLanguagesChanged() { propertyChanged(PreferredLanguagesRole); } void QOfonoExtSimListModel::SimData::onPinRetriesChanged() { propertyChanged(PinRetriesRole); } void QOfonoExtSimListModel::SimData::onFixedDialingChanged() { propertyChanged(FixedDialingRole); } void QOfonoExtSimListModel::SimData::onBarredDialingChanged() { propertyChanged(BarredDialingRole); } // ========================================================================== // QOfonoExtSimListModel // ========================================================================== QOfonoExtSimListModel::QOfonoExtSimListModel(QObject *aParent) : QAbstractListModel(aParent), iModemManager(QOfonoExtModemManager::instance()), iSimWatcher(new QOfonoSimWatcher(this)), iValid(false) { iSimWatcher->setRequireSubscriberIdentity(false); QList sims(iSimWatcher->presentSimList()); for (int i=0; i QOfonoExtSimListModel::roleNames() const { QHash roles; roles[SlotRole] = "slot"; roles[PathRole] = "path"; roles[ValidRole] = "valid"; roles[SubscriberIdentityRole] = "subscriberIdentity"; roles[MobileCountryCodeRole] = "mobileCountryCode"; roles[MobileNetworkCodeRole] = "mobileNetworkCode"; roles[ServiceProviderNameRole] = "serviceProviderName"; roles[SubscriberNumbersRole] = "subscriberNumbers"; roles[ServiceNumbersRole] = "serviceNumbers"; roles[PinRequiredRole] = "pinRequired"; roles[LockedPinsRole] = "lockedPins"; roles[CardIdentifierRole] = "cardIdentifier"; roles[PreferredLanguagesRole] = "preferredLanguages"; roles[PinRetriesRole] = "pinRetries"; roles[FixedDialingRole] = "fixedDialing"; roles[BarredDialingRole] = "barredDialing"; return roles; } int QOfonoExtSimListModel::rowCount(const QModelIndex&) const { return iSimList.count(); } QVariant QOfonoExtSimListModel::data(const QModelIndex& aIndex, int aRole) const { const int row = aIndex.row(); if (row >= 0 && row < iSimList.count()) { const SimData* d = iSimList.at(row); switch (aRole) { case SlotRole: return d->iSlot; case ValidRole: return d->iValid; case PathRole: return d->iSim->modemPath(); case MobileCountryCodeRole: return d->iSim->mobileCountryCode(); case MobileNetworkCodeRole: return d->iSim->mobileNetworkCode(); case SubscriberNumbersRole: return d->iSim->subscriberNumbers(); case ServiceNumbersRole: return d->iSim->serviceNumbers(); case PinRequiredRole: return d->iSim->pinRequired(); case LockedPinsRole: return d->iSim->lockedPins(); case CardIdentifierRole: return d->iSim->cardIdentifier(); case PreferredLanguagesRole: return d->iSim->preferredLanguages(); case PinRetriesRole: return d->iSim->pinRetries(); case FixedDialingRole: return d->iSim->fixedDialing(); case BarredDialingRole: return d->iSim->barredDialing(); case SubscriberIdentityRole: return d->iCache->subscriberIdentity(); case ServiceProviderNameRole: return d->iCache->serviceProviderName(); } } else { qWarning() << aIndex << aRole; } return QVariant(); } void QOfonoExtSimListModel::onPresentSimListChanged() { QList sims; if (iSimWatcher->isValid()) { sims = iSimWatcher->presentSimList(); } const bool countHasChanged(iSimList.count() != sims.count()); const bool wasValid = iValid; QStringList paths; int i; for (i=0; imodemPath()); } // Remove stale entries for (i=iSimList.count()-1; i>=0; i--) { QString path(iSimList.at(i)->iSim->modemPath()); if (!paths.contains(path)) { beginRemoveRows(QModelIndex(), i, i); delete iSimList.takeAt(i); endRemoveRows(); Q_EMIT simRemoved(path); } } // Add new entries for (i=0; iiSim->modemPath() != paths.at(i)) { SimData* data = new SimData(this, iModemManager, sims.at(i), i); beginInsertRows(QModelIndex(), i, i); iSimList.insert(i, data); endInsertRows(); Q_EMIT simAdded(data->iCache); } else { iSimList.at(i)->iIndex = i; } } if (countHasChanged) { Q_EMIT countChanged(); } iValid = isValid(); if (iValid != wasValid) { Q_EMIT validChanged(); } } bool QOfonoExtSimListModel::isValid() const { bool valid = iSimWatcher->isValid(); for (int i=0; valid && iiValid) { valid = false; } } return valid; } void QOfonoExtSimListModel::checkValid() { const bool wasValid = iValid; iValid = isValid(); if (iValid != wasValid) { Q_EMIT validChanged(); } } #include "qofonoextsimlistmodel.moc" libqofonoext-1.0.32/plugin/qofonoextsimlistmodel.h000066400000000000000000000044351457630555700224540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTSIMLISTMODEL_H #define QOFONOEXTSIMLISTMODEL_H #include "qofonosimwatcher.h" #include "qofonoextsiminfo.h" #include "qofonoextmodemmanager.h" class QOfonoExtSimListModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) public: enum Role { PathRole = Qt::UserRole + 1, SlotRole, ValidRole, SubscriberIdentityRole, MobileCountryCodeRole, MobileNetworkCodeRole, ServiceProviderNameRole, SubscriberNumbersRole, ServiceNumbersRole, PinRequiredRole, LockedPinsRole, CardIdentifierRole, PreferredLanguagesRole, PinRetriesRole, FixedDialingRole, BarredDialingRole }; explicit QOfonoExtSimListModel(QObject* aParent = NULL); bool valid() const; int count() const; protected: QHash roleNames() const; int rowCount(const QModelIndex& aParent) const; QVariant data(const QModelIndex& aIndex, int aRole) const; Q_SIGNALS: void validChanged(); void countChanged(); void simAdded(QOfonoExtSimInfo* sim); void simRemoved(QString path); private Q_SLOTS: void onPresentSimListChanged(); private: void checkValid(); bool isValid() const; private: class SimData; friend class SimData; QSharedPointer iModemManager; QOfonoSimWatcher* iSimWatcher; QList iSimList; bool iValid; }; #endif // QOFONOEXTSIMLISTMODEL_H libqofonoext-1.0.32/rpm/000077500000000000000000000000001457630555700151255ustar00rootroot00000000000000libqofonoext-1.0.32/rpm/libqofonoext.spec000066400000000000000000000034131457630555700205130ustar00rootroot00000000000000Name: libqofonoext Summary: A library of Qt bindings for ofono extensions Version: 1.0.31 Release: 1 License: LGPLv2 URL: https://github.com/sailfishos/libqofonoext Source0: %{name}-%{version}.tar.bz2 %define libqofono_version 0.101 BuildRequires: pkgconfig BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(Qt5DBus) BuildRequires: pkgconfig(Qt5Quick) BuildRequires: pkgconfig(qofono-qt5) >= %{libqofono_version} # license macro requires rpm >= 4.11 BuildRequires: pkgconfig(rpm) %define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?) Requires: libqofono-qt5 >= %{libqofono_version} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %{!?qtc_qmake5:%define qtc_qmake5 %qmake5} %{!?qtc_make:%define qtc_make make} %description This package contains Qt bindings for ofono extensions %package declarative Summary: Declarative plugin for %{name} Requires: %{name} = %{version}-%{release} Requires: %{name} = %{version} %description declarative This package contains declarative plugin for %{name} %package devel Summary: Development files for %{name} Requires: %{name} = %{version}-%{release} Requires: %{name} = %{version} %description devel This package contains the development header files for %{name} %prep %setup -q -n %{name}-%{version} %build %qtc_qmake5 %qtc_make %{?_smp_mflags} %install rm -rf %{buildroot} %qmake5_install %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_libdir}/%{name}.so.* %if %{license_support} == 0 %license LICENSE.LGPL %endif %files declarative %defattr(-,root,root,-) %{_libdir}/qt5/qml/org/nemomobile/ofono %files devel %defattr(-,root,root,-) %{_libdir}/%{name}.so %{_libdir}/pkgconfig/qofonoext.pc %{_includedir}/qofonoext/*.h libqofonoext-1.0.32/src/000077500000000000000000000000001457630555700151165ustar00rootroot00000000000000libqofonoext-1.0.32/src/qofonoext.cpp000066400000000000000000000017501457630555700176470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoext_p.h" bool QOfonoExt::isTimeout(QDBusError aError) { switch (aError.type()) { case QDBusError::NoReply: case QDBusError::Timeout: case QDBusError::TimedOut: return true; default: return false; } } libqofonoext-1.0.32/src/qofonoext.prf000066400000000000000000000002461457630555700176530ustar00rootroot00000000000000prefix=/usr exec_prefix=$${prefix} DEPENDPATH += $${prefix}/include/qofonoext INCLUDEPATH += $${prefix}/include/qofonoext LIBS += -L $${exec_prefix}/lib -lqofonoext libqofonoext-1.0.32/src/qofonoext_p.h000066400000000000000000000020511457630555700176260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXT_PRIVATE_H #define QOFONOEXT_PRIVATE_H #include "qofonoext_types.h" #include #define OFONO_SERVICE "org.ofono" #define OFONO_BUS QDBusConnection::systemBus() typedef QList QOfonoExtBoolList; namespace QOfonoExt { bool isTimeout(QDBusError aError); } #endif // QOFONOEXT_PRIVATE_H libqofonoext-1.0.32/src/qofonoext_types.h000066400000000000000000000020101457630555700205260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXT_TYPES_H #define QOFONOEXT_TYPES_H #include #ifndef QOFONOEXT_EXPORT # if defined(QOFONOEXT_LIBRARY) # define QOFONOEXT_EXPORT Q_DECL_EXPORT # else # define QOFONOEXT_EXPORT Q_DECL_IMPORT # endif #endif // QOFONOEXT_EXPORT #endif // QOFONOEXT_TYPES_H libqofonoext-1.0.32/src/qofonoextcell.cpp000066400000000000000000000351041457630555700205070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2023 Slava Monich ** Copyright (C) 2015-2021 Jolla Ltd. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextcell.h" #include "qofonoextcellinfo.h" #include "qofonoext_p.h" namespace { const QString kTypeGsm("gsm"); const QString kTypeWcdma("wcdma"); const QString kTypeLte("lte"); const QString kTypeNr("nr"); const QString kMethodGetAll("GetAll"); } #define QOFONOEXT_INVALID_VALUE ((int)QOfonoExtCell::InvalidValue) #define CELL_PROPERTIES(p) \ p(mcc) p(mnc) p(signalStrength) p(lac) p(cid) p(arfcn) p(bsic) \ p(bitErrorRate) p(psc) p(uarfcn) p(ci) p(pci) p(tac) p(earfcn) p(rsrp) \ p(rsrq) p(rssnr) p(cqi) p(timingAdvance) p(nrarfcn) \ p(ssRsrp) p(ssRsrq) p(ssSinr) p(csiRsrp) p(csiRsrq) p(csiSinr) // ========================================================================== // QOfonoExtCellProxy // // qdbusxml2cpp doesn't really do much, and has a number of limitations, // such as the limits on number of arguments for QDBusPendingReply template. // It's easier to write these proxies by hand. // ========================================================================== class QOfonoExtCellProxy: public QDBusAbstractInterface { Q_OBJECT public: QOfonoExtCellProxy(const QString &aPath, QObject *aParent) : QDBusAbstractInterface(OFONO_SERVICE, aPath, "org.nemomobile.ofono.Cell", OFONO_BUS, aParent) {} public Q_SLOTS: // METHODS QDBusPendingCall GetAllAsync() { return asyncCall(kMethodGetAll); } QDBusMessage GetAllSync() { return call(kMethodGetAll); } Q_SIGNALS: // SIGNALS void PropertyChanged(const QString &aName, const QDBusVariant &aValue); void RegisteredChanged(bool aRegistered); void Removed(); }; // ========================================================================== // QOfonoExtCell::Private // ========================================================================== class QOfonoExtCell::Private : public QOfonoExtCellProxy { Q_OBJECT public: enum Property { PropertyUnknown = -1, #define Property_(x) Property_##x, CELL_PROPERTIES(Property_) PropertyCount }; struct PropertyDesc { QString name; void (QOfonoExtCell::*signal)(); void (*propertyChanged)(QOfonoExtCell*, QString, int); }; static const PropertyDesc Properties[PropertyCount]; typedef QDBusPendingReply < int, // 0. version QString, // 1. type bool, // 2. registered QVariantMap> // 3. properties GetAllReply; Private(const QString &aPath, QOfonoExtCell *aParent); void getAllSyncInit(); static int valueInt(Private* aThis, Property aProperty); static Type typeFromString(const QString &aType); static Property propertyFromString(const QString &aProperty); static int getRssiDbm(int aSignalStrength); static int inRange(int aValue, int aRangeMin, int aRangeMax); private: QOfonoExtCell* cell(); void getAllAsync(); bool pathValid(); bool updateSignalLevelDbm(); void handleGetAllReply(GetAllReply aReply, bool aEmitSignals); void invalidateValues(); static void propertyChanged(QOfonoExtCell* aCell, QString aName, int aValue); public Q_SLOTS: void updateAllAsync(); private Q_SLOTS: void onGetAllFinished(QDBusPendingCallWatcher* aWatcher); void onPropertyChanged(const QString &aName, const QDBusVariant &aValue); void onRegisteredChanged(bool aRegistered); public: bool iValid; bool iRegistered; int iProperties[PropertyCount]; int iSignalLevelDbm; QOfonoExtCell::Type iType; qint64 iNci; private: QDBusPendingCallWatcher* iPendingGetAll; QSharedPointer iCellInfo; }; void QOfonoExtCell::Private::propertyChanged(QOfonoExtCell* aCell, QString aName, int aValue) { Q_EMIT aCell->propertyChanged(aName, aValue); } const QOfonoExtCell::Private::PropertyDesc QOfonoExtCell::Private::Properties[] = { #define PropertyDesc_(x) {QString(#x), &QOfonoExtCell::x##Changed, propertyChanged}, CELL_PROPERTIES(PropertyDesc_) }; QOfonoExtCell::Private::Private(const QString &aPath, QOfonoExtCell *aParent) : QOfonoExtCellProxy(aPath, aParent), iValid(false), iRegistered(false), iSignalLevelDbm(QOFONOEXT_INVALID_VALUE), iType(UNKNOWN), iNci(INT64_MAX), iPendingGetAll(Q_NULLPTR) { // Extract modem path from the cell path, e.g. "/ril_0/cell_0" => "/ril_0" iCellInfo = QOfonoExtCellInfo::instance(aPath.left(aPath.lastIndexOf('/'))); invalidateValues(); connect(this, SIGNAL(Removed()), aParent, SIGNAL(removed())); connect(this, SIGNAL(PropertyChanged(QString,QDBusVariant)), SLOT(onPropertyChanged(QString,QDBusVariant))); connect(this, SIGNAL(RegisteredChanged(bool)), SLOT(onRegisteredChanged(bool))); connect(iCellInfo.data(), SIGNAL(cellsChanged()), SLOT(updateAllAsync())); connect(iCellInfo.data(), SIGNAL(validChanged()), SLOT(updateAllAsync())); } inline QOfonoExtCell* QOfonoExtCell::Private::cell() { return qobject_cast(parent()); } QOfonoExtCell::Type QOfonoExtCell::Private::typeFromString(const QString &aType) { return (aType == kTypeGsm) ? GSM : (aType == kTypeLte) ? LTE : (aType == kTypeWcdma) ? WCDMA : (aType == kTypeNr) ? NR : UNKNOWN; } QOfonoExtCell::Private::Property QOfonoExtCell::Private::propertyFromString(const QString &aProperty) { for (int i=PropertyUnknown+1; iiProperties[aProperty] : QOFONOEXT_INVALID_VALUE; } bool QOfonoExtCell::Private::pathValid() { return iCellInfo->valid() && iCellInfo->cells().contains(path()); } void QOfonoExtCell::Private::updateAllAsync() { if (pathValid()) { if (!iValid && !iPendingGetAll) { getAllAsync(); } } else { delete iPendingGetAll; iPendingGetAll = Q_NULLPTR; if (iValid) { iValid = false; Q_EMIT cell()->validChanged(); } } } int QOfonoExtCell::Private::getRssiDbm(int aValue) { // Range for RSSI in ASU (0-31, 99) as defined in TS 27.007 8.69 return (aValue < 0 || aValue > 31) ? QOFONOEXT_INVALID_VALUE : (-113 + (2 * aValue)); } int QOfonoExtCell::Private::inRange(int aValue, int aMin, int aMax) { return (aValue < aMin || aValue > aMax) ? QOFONOEXT_INVALID_VALUE : aValue; } void QOfonoExtCell::Private::getAllSyncInit() { delete iPendingGetAll; iPendingGetAll = NULL; GetAllReply reply(GetAllSync()); if (!reply.isError()) { handleGetAllReply(reply, false); } } void QOfonoExtCell::Private::getAllAsync() { delete iPendingGetAll; iPendingGetAll = new QDBusPendingCallWatcher(GetAllAsync(), this); connect(iPendingGetAll, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onGetAllFinished(QDBusPendingCallWatcher*))); } void QOfonoExtCell::Private::onGetAllFinished(QDBusPendingCallWatcher* aWatcher) { iPendingGetAll = Q_NULLPTR; if (aWatcher->isError()) { // Repeat the call on timeout QDBusError error(aWatcher->error()); qWarning() << error; if (QOfonoExt::isTimeout(error)) { getAllAsync(); } } else { handleGetAllReply(*aWatcher, true); } aWatcher->deleteLater(); } void QOfonoExtCell::Private::handleGetAllReply(GetAllReply aReply, bool aEmitSignals) { const Type prevType = iType; const bool wasRegistered = iRegistered; const int prevSignalLevelDbm = iSignalLevelDbm; const qint64 prevNci = iNci; // Ignore argumentAt<0> version iType = typeFromString(aReply.argumentAt<1>()); iRegistered = aReply.argumentAt<2>(); const QVariantMap variants(aReply.argumentAt<3>()); // Unpack properties (they are all integers) int prevProps[PropertyCount]; memcpy(prevProps, iProperties, sizeof(iProperties)); invalidateValues(); for (QVariantMap::ConstIterator it = variants.constBegin(); it != variants.constEnd(); it++) { const QString key(it.key()); const QVariant value(it.value()); if (key == QLatin1String("nci")) { bool ok = false; qint64 int64Value = value.toLongLong(&ok); if (ok) { iNci = int64Value; } } else { bool ok = false; int intValue = value.toInt(&ok); if (ok) { Property p = propertyFromString(key); if (p != PropertyUnknown) { iProperties[p] = intValue; } } } } // This one is a combination of other properties, updated separately updateSignalLevelDbm(); // Emit signals if (aEmitSignals) { QOfonoExtCell* parent = cell(); for (int i=0; i*(Properties[i].signal))(); Properties[i].propertyChanged(parent, Properties[i].name, iProperties[i]); } } if (prevNci != iNci) { Q_EMIT parent->nciChanged(); } iValid = true; if (prevType != iType) { Q_EMIT parent->typeChanged(); } if (wasRegistered != iRegistered) { Q_EMIT parent->registeredChanged(); } if (prevSignalLevelDbm != iSignalLevelDbm) { Q_EMIT parent->signalLevelDbmChanged(); } Q_EMIT parent->signalLevelDbmChanged(); Q_EMIT parent->validChanged(); } } void QOfonoExtCell::Private::invalidateValues() { #define _Init(x) iProperties[Property_##x] = QOFONOEXT_INVALID_VALUE; CELL_PROPERTIES(_Init) iNci = INT64_MAX; } void QOfonoExtCell::Private::onPropertyChanged(const QString &aName, const QDBusVariant &aValue) { bool ok = false; int intValue = aValue.variant().toInt(&ok); if (ok) { Property p = propertyFromString(aName); if (p != PropertyUnknown && iProperties[p] != intValue) { QOfonoExtCell* parent = cell(); iProperties[p] = intValue; Q_EMIT (parent->*(Properties[p].signal))(); Q_EMIT parent->propertyChanged(aName, intValue); switch (p) { case Property_signalStrength: case Property_rsrp: if (updateSignalLevelDbm()) { Q_EMIT parent->signalLevelDbmChanged(); } break; case Property_ssRsrp: if (updateSignalLevelDbm()) { Q_EMIT parent->signalLevelDbmChanged(); } break; default: break; } } } } void QOfonoExtCell::Private::onRegisteredChanged(bool aRegistered) { iRegistered = aRegistered; Q_EMIT cell()->registeredChanged(); } bool QOfonoExtCell::Private::updateSignalLevelDbm() { int signalLevelDbm = QOFONOEXT_INVALID_VALUE; switch (iType) { case NR: // Return SS-RSRP value. Reference: 3GPP TS 36.133, sub-clause 9.11 signalLevelDbm = inRange(-iProperties[Property_ssRsrp], -140, -44); break; case LTE: // Return RSRP value. Reference: 3GPP TS 36.133, sub-clause 9.1.4 signalLevelDbm = inRange(-iProperties[Property_rsrp], -140, -44); break; case WCDMA: case GSM: // Return RSSI. Reference: TS 27.007 sub clause 8.5 signalLevelDbm = getRssiDbm(iProperties[Property_signalStrength]); break; case UNKNOWN: break; } if (iSignalLevelDbm != signalLevelDbm) { iSignalLevelDbm = signalLevelDbm; return true; } return false; } // ========================================================================== // QOfonoExtCell // ========================================================================== QOfonoExtCell::QOfonoExtCell(QObject* aParent) : QObject(aParent), iPrivate(Q_NULLPTR) { } QOfonoExtCell::QOfonoExtCell(QString aPath) : iPrivate(new Private(aPath, this)) { iPrivate->updateAllAsync(); } QOfonoExtCell::QOfonoExtCell(QString aPath, bool aMayBlock) : // Since 1.0.27 iPrivate(new Private(aPath, this)) { if (aMayBlock) { iPrivate->getAllSyncInit(); } else { iPrivate->updateAllAsync(); } } QOfonoExtCell::~QOfonoExtCell() { } bool QOfonoExtCell::valid() const { return iPrivate && iPrivate->iValid; } QOfonoExtCell::Type QOfonoExtCell::type() const { return iPrivate ? iPrivate->iType : UNKNOWN; } bool QOfonoExtCell::registered() const { return iPrivate && iPrivate->iRegistered; } QString QOfonoExtCell::path() const { return iPrivate ? iPrivate->path() : QString(); } void QOfonoExtCell::setPath(QString aPath) { if (path() != aPath) { const bool wasValid = valid(); const bool wasRegistered = registered(); const Type prevType = type(); delete iPrivate; iPrivate = new Private(aPath, this); iPrivate->updateAllAsync(); if (valid() != wasValid) { Q_EMIT validChanged(); } if (registered() != wasRegistered) { Q_EMIT registeredChanged(); } if (type() != prevType) { Q_EMIT typeChanged(); } Q_EMIT pathChanged(); } } int QOfonoExtCell::signalLevelDbm() const { return iPrivate ? iPrivate->iSignalLevelDbm : QOFONOEXT_INVALID_VALUE; } #define PropertyGet_(x) \ int QOfonoExtCell::x() const {\ return Private::valueInt(iPrivate, Private::Property_##x); \ } CELL_PROPERTIES(PropertyGet_) QString QOfonoExtCell::nciString() const { qint64 value = iPrivate ? iPrivate->iNci : INT64_MAX; if (value != INT64_MAX) { return QString::number(value); } return QString(); } #include "qofonoextcell.moc" libqofonoext-1.0.32/src/qofonoextcell.h000066400000000000000000000121621457630555700201530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2023 Slava Monich ** Copyright (C) 2015-2021 Jolla Ltd. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTCELL_H #define QOFONOEXTCELL_H #include "qofonoext_types.h" class QOFONOEXT_EXPORT QOfonoExtCell : public QObject { Q_OBJECT Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(Type type READ type NOTIFY typeChanged) Q_PROPERTY(bool registered READ registered NOTIFY registeredChanged) Q_PROPERTY(int mcc READ mcc NOTIFY mccChanged) Q_PROPERTY(int mnc READ mnc NOTIFY mncChanged) Q_PROPERTY(int signalStrength READ signalStrength NOTIFY signalStrengthChanged) Q_PROPERTY(int lac READ lac NOTIFY lacChanged) Q_PROPERTY(int cid READ cid NOTIFY cidChanged) Q_PROPERTY(int arfcn READ arfcn NOTIFY arfcnChanged) Q_PROPERTY(int bsic READ bsic NOTIFY bsicChanged) Q_PROPERTY(int bitErrorRate READ bitErrorRate NOTIFY bitErrorRateChanged) Q_PROPERTY(int psc READ psc NOTIFY pscChanged) Q_PROPERTY(int uarfcn READ uarfcn NOTIFY uarfcnChanged) Q_PROPERTY(int ci READ ci NOTIFY ciChanged) Q_PROPERTY(int pci READ pci NOTIFY pciChanged) Q_PROPERTY(int tac READ tac NOTIFY tacChanged) Q_PROPERTY(int earfcn READ earfcn NOTIFY earfcnChanged) Q_PROPERTY(int rsrp READ rsrp NOTIFY rsrpChanged) Q_PROPERTY(int rsrq READ rsrq NOTIFY rsrqChanged) Q_PROPERTY(int rssnr READ rssnr NOTIFY rssnrChanged) Q_PROPERTY(int cqi READ cqi NOTIFY cqiChanged) Q_PROPERTY(int timingAdvance READ timingAdvance NOTIFY timingAdvanceChanged) // string to allow easy usage from qml Q_PROPERTY(QString nci READ nciString NOTIFY nciChanged) Q_PROPERTY(int nrarfcn READ nrarfcn NOTIFY nrarfcnChanged) Q_PROPERTY(int ssRsrp READ ssRsrp NOTIFY ssRsrpChanged) Q_PROPERTY(int ssRsrq READ ssRsrq NOTIFY ssRsrqChanged) Q_PROPERTY(int ssSinr READ ssSinr NOTIFY ssSinrChanged) Q_PROPERTY(int csiRsrp READ csiRsrp NOTIFY csiRsrpChanged) Q_PROPERTY(int csiRsrq READ csiRsrq NOTIFY csiRsrqChanged) Q_PROPERTY(int csiSinr READ csiSinr NOTIFY csiSinrChanged) Q_PROPERTY(int signalLevelDbm READ signalLevelDbm NOTIFY signalLevelDbmChanged) Q_ENUMS(Type) Q_ENUMS(Constants) public: enum Type { Unknown, GSM, WCDMA, LTE, NR, UNKNOWN = Unknown // For backward compatibility }; enum Constants { InvalidValue = INT_MAX }; explicit QOfonoExtCell(QObject* aParent = Q_NULLPTR); QOfonoExtCell(QString aPath, bool aMayBlock); // Since 1.0.27 QOfonoExtCell(QString aPath); ~QOfonoExtCell(); QString path() const; void setPath(QString aPath); bool valid() const; Type type() const; bool registered() const; // All types: int mcc() const; int mnc() const; int signalStrength() const; int signalLevelDbm() const; // GSM: int arfcn() const; int bsic() const; // GSM and WCDMA: int lac() const; int cid() const; int bitErrorRate() const; // WCDMA: int psc() const; int uarfcn() const; // LTE: int ci() const; int earfcn() const; int rsrp() const; int rsrq() const; int rssnr() const; int cqi() const; int timingAdvance() const; // LTE and NR: int pci() const; int tac() const; // NR: QString nciString() const; int nrarfcn() const; int ssRsrp() const; int ssRsrq() const; int ssSinr() const; int csiRsrp() const; int csiRsrq() const; int csiSinr() const; Q_SIGNALS: void validChanged(); void pathChanged(); void typeChanged(); void registeredChanged(); void mccChanged(); void mncChanged(); void signalStrengthChanged(); void lacChanged(); void cidChanged(); void arfcnChanged(); void bsicChanged(); void bitErrorRateChanged(); void pscChanged(); void uarfcnChanged(); void ciChanged(); void pciChanged(); void tacChanged(); void earfcnChanged(); void rsrpChanged(); void rsrqChanged(); void rssnrChanged(); void cqiChanged(); void timingAdvanceChanged(); void nciChanged(); void nrarfcnChanged(); void ssRsrpChanged(); void ssRsrqChanged(); void ssSinrChanged(); void csiRsrpChanged(); void csiRsrqChanged(); void csiSinrChanged(); void signalLevelDbmChanged(); void propertyChanged(QString name, int value); // int properties void removed(); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTCELL_H libqofonoext-1.0.32/src/qofonoextcellinfo.cpp000066400000000000000000000236521457630555700213700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextcellinfo.h" #include "qofonoext_p.h" #include static const QString kMethodGetCells("GetCells"); typedef QMap > QOfonoExtCellInfoMap; Q_GLOBAL_STATIC(QOfonoExtCellInfoMap, sharedInstances) // ========================================================================== // QOfonoExtCellInfoProxy // // qdbusxml2cpp doesn't really do much, and has a number of limitations, // such as the limits on number of arguments for QDBusPendingReply template. // It's easier to write these proxies by hand. // ========================================================================== class QOfonoExtCellInfoProxy: public QDBusAbstractInterface { Q_OBJECT public: static const QString INTERFACE; QOfonoExtCellInfoProxy(QString aPath, QObject* aParent) : QDBusAbstractInterface(OFONO_SERVICE, aPath, qPrintable(INTERFACE), OFONO_BUS, aParent) {} public Q_SLOTS: // METHODS QDBusPendingCall GetCellsAsync() { return asyncCall(kMethodGetCells); } QDBusMessage GetCellsSync() { return call(kMethodGetCells); } Q_SIGNALS: // SIGNALS void CellsAdded(QList aPaths); void CellsRemoved(QList aPaths); }; const QString QOfonoExtCellInfoProxy::INTERFACE("org.nemomobile.ofono.CellInfo"); // ========================================================================== // QOfonoExtCellInfo::Private // ========================================================================== class QOfonoExtCellInfo::Private : public QObject { Q_OBJECT public: Private(QOfonoExtCellInfo* aParent); QString modemPath() const; void setModemPath(QString aPath); void setModemPathSyncInit(QString aPath); private: void getCellsSyncInit(); void getCellsAsync(); void invalidate(); void setModemPath(QString aPath, QSharedPointer aModem, void (Private::*aGetCells)()); void checkInterfacePresence(void (Private::*getCellsFn)()); static QStringList getPaths(const QList aPaths); private Q_SLOTS: void onModemChanged(); void onGetCellsFinished(QDBusPendingCallWatcher* aWatcher); void onCellsAdded(QList aCells); void onCellsRemoved(QList aCells); public: bool iValid; bool iFixedPath; QStringList iCells; private: QOfonoExtCellInfo* iParent; QOfonoExtCellInfoProxy* iProxy; QSharedPointer iModem; }; QOfonoExtCellInfo::Private::Private(QOfonoExtCellInfo* aParent) : QObject(aParent), iValid(false), iFixedPath(false), iParent(aParent), iProxy(NULL) { } inline QString QOfonoExtCellInfo::Private::modemPath() const { return iModem.isNull() ? QString() : iModem->objectPath(); } inline void QOfonoExtCellInfo::Private::setModemPath(QString aPath) { setModemPath(aPath, QOfonoModem::instance(aPath), &Private::getCellsAsync); } inline void QOfonoExtCellInfo::Private::setModemPathSyncInit(QString aPath) { setModemPath(aPath, QOfonoModem::instance(aPath, true), &Private::getCellsSyncInit); } void QOfonoExtCellInfo::Private::setModemPath(QString aPath, QSharedPointer aModem, void (Private::*aGetCells)()) { // Caller has checked the the path has actually changed invalidate(); if (aPath.isEmpty()) { if (iModem) { iModem->disconnect(this); iModem.clear(); } } else { if (iModem) iModem->disconnect(this); iModem = aModem; connect(iModem.data(), SIGNAL(validChanged(bool)), SLOT(onModemChanged())); connect(iModem.data(), SIGNAL(interfacesChanged(QStringList)), SLOT(onModemChanged())); checkInterfacePresence(aGetCells); } } void QOfonoExtCellInfo::Private::getCellsAsync() { connect(new QDBusPendingCallWatcher(iProxy->GetCellsAsync(), iProxy), SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onGetCellsFinished(QDBusPendingCallWatcher*))); } void QOfonoExtCellInfo::Private::getCellsSyncInit() { QDBusPendingReply > reply(iProxy->GetCellsSync()); if (!reply.isError()) { iCells = getPaths(reply.value()); iValid = true; } else { // Repeat call asynchronously on timeout QDBusError error(reply.error()); qWarning() << error; if (QOfonoExt::isTimeout(error)) { getCellsAsync(); } } } void QOfonoExtCellInfo::Private::checkInterfacePresence(void (Private::*aGetCells)()) { if (iModem && iModem->isValid() && iModem->interfaces().contains(QOfonoExtCellInfoProxy::INTERFACE)) { if (!iProxy) { iProxy = new QOfonoExtCellInfoProxy(iModem->objectPath(), this); if (iProxy->isValid()) { connect(iProxy, SIGNAL(CellsAdded(QList)), SLOT(onCellsAdded(QList))); connect(iProxy, SIGNAL(CellsRemoved(QList)), SLOT(onCellsRemoved(QList))); (this->*aGetCells)(); } else { invalidate(); } } } else { invalidate(); } } void QOfonoExtCellInfo::Private::invalidate() { if (iProxy) { delete iProxy; iProxy = NULL; } if (iValid) { iValid = false; Q_EMIT iParent->validChanged(); } } QStringList QOfonoExtCellInfo::Private::getPaths(const QList aPaths) { QStringList list; const int n = aPaths.count(); for (int i = 0; i < n; i++) { list.append(aPaths.at(i).path()); } list.sort(); return list; } void QOfonoExtCellInfo::Private::onGetCellsFinished(QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply > reply(*aWatcher); if (reply.isError()) { // Repeat the call on timeout QDBusError error(reply.error()); qWarning() << error; if (QOfonoExt::isTimeout(error)) { getCellsAsync(); } } else { const QStringList list(getPaths(reply.value())); if (iCells != list) { iCells = list; Q_EMIT iParent->cellsChanged(); } if (!iValid) { iValid = true; Q_EMIT iParent->validChanged(); } } aWatcher->deleteLater(); } void QOfonoExtCellInfo::Private::onModemChanged() { checkInterfacePresence(&Private::getCellsAsync); } void QOfonoExtCellInfo::Private::onCellsAdded(QList aCells) { QStringList cells; for (int i=0; icellsAdded(cells); Q_EMIT iParent->cellsChanged(); } } void QOfonoExtCellInfo::Private::onCellsRemoved(QList aCells) { QStringList cells; for (int i=0; icellsRemoved(cells); Q_EMIT iParent->cellsChanged(); } } // ========================================================================== // QOfonoExtCellInfo // ========================================================================== QOfonoExtCellInfo::QOfonoExtCellInfo(QObject* aParent) : QObject(aParent), iPrivate(new Private(this)) { } QOfonoExtCellInfo::QOfonoExtCellInfo(QString aModemPath, QObject* aParent) : // Since 1.0.27 QObject(aParent), iPrivate(new Private(this)) { iPrivate->setModemPathSyncInit(aModemPath); // Blocks } QOfonoExtCellInfo::~QOfonoExtCellInfo() { } QSharedPointer QOfonoExtCellInfo::instance(QString aPath) { return instance(aPath, false); // Don't block } QSharedPointer QOfonoExtCellInfo::instance(QString aPath, bool aMayBlock) // Since 1.0.27 { QSharedPointer ptr = sharedInstances()->value(aPath); if (ptr.isNull()) { QOfonoExtCellInfo* cellInfo; if (aMayBlock) { cellInfo = new QOfonoExtCellInfo(aPath); // Blocks } else { cellInfo = new QOfonoExtCellInfo(); cellInfo->setModemPath(aPath); } cellInfo->iPrivate->iFixedPath = true; ptr = QSharedPointer(cellInfo, &QObject::deleteLater); sharedInstances()->insert(aPath, QWeakPointer(ptr)); } return ptr; } bool QOfonoExtCellInfo::valid() const { return iPrivate->iValid; } QString QOfonoExtCellInfo::modemPath() const { return iPrivate->modemPath(); } QStringList QOfonoExtCellInfo::cells() const { return iPrivate->iCells; } void QOfonoExtCellInfo::setModemPath(QString aModemPath) { if (iPrivate->modemPath() != aModemPath) { if (iPrivate->iFixedPath) { qWarning() << "Attempting to change fixed path" << iPrivate->modemPath(); } else { iPrivate->setModemPath(aModemPath); } } } #include "qofonoextcellinfo.moc" libqofonoext-1.0.32/src/qofonoextcellinfo.h000066400000000000000000000036041457630555700210300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTCELLINFO_H #define QOFONOEXTCELLINFO_H #include "qofonoext_types.h" class QOFONOEXT_EXPORT QOfonoExtCellInfo : public QObject { Q_OBJECT Q_PROPERTY(QString modemPath READ modemPath WRITE setModemPath NOTIFY modemPathChanged) Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(QStringList cells READ cells NOTIFY cellsChanged) public: explicit QOfonoExtCellInfo(QObject* aParent = Q_NULLPTR); QOfonoExtCellInfo(QString aModemPath, QObject* aParent = Q_NULLPTR); // Blocks (since 1.0.27) ~QOfonoExtCellInfo(); // Shared instance(s) for C++ use static QSharedPointer instance(QString aModemPath); static QSharedPointer instance(QString aModemPath, bool aMayBlock); // Since 1.0.27 QString modemPath() const; void setModemPath(QString aModemPath); bool valid() const; QStringList cells() const; Q_SIGNALS: void validChanged(); void modemPathChanged(); void cellsChanged(); void cellsAdded(QStringList cells); void cellsRemoved(QStringList cells); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTCELLINFO_H libqofonoext-1.0.32/src/qofonoextcellwatcher.cpp000066400000000000000000000126041457630555700220650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextcellwatcher.h" #include "qofonoextcellinfo.h" #include "qofonomanager.h" class QOfonoExtCellWatcher::Private : public QObject { Q_OBJECT public: Private(QOfonoExtCellWatcher* aParent); QOfonoExtCellWatcher* iParent; QSharedPointer iOfonoManager; QList > iCellInfoList; QList > iValidCells; QMap > iKnownCells; private: void updateCellInfo(); QStringList updateKnownCells(); public Q_SLOTS: void updateValidCells(); }; QOfonoExtCellWatcher::Private::Private(QOfonoExtCellWatcher* aParent) : QObject(aParent), iParent(aParent), iOfonoManager(QOfonoManager::instance()) { connect(iOfonoManager.data(), SIGNAL(availableChanged(bool)), SLOT(updateValidCells())); connect(iOfonoManager.data(), SIGNAL(modemsChanged(QStringList)), SLOT(updateValidCells())); updateValidCells(); } void QOfonoExtCellWatcher::Private::updateCellInfo() { int i; QStringList modems; if (iOfonoManager->available()) { modems = iOfonoManager->modems(); } modems.sort(); bool changed = true; if (modems.count() == iCellInfoList.count()) { changed = false; for (i=0; imodemPath() != modems.at(i)) { changed = true; break; } } } if (changed) { QList > bak(iCellInfoList); for (i=0; idisconnect(this); } iCellInfoList.clear(); for (i=0; i cellInfo = QOfonoExtCellInfo::instance(modems.at(i)); iCellInfoList.append(cellInfo); connect(cellInfo.data(), SIGNAL(cellsChanged()), SLOT(updateValidCells())); } } } QStringList QOfonoExtCellWatcher::Private::updateKnownCells() { updateCellInfo(); QStringList allCells; int i; for (i=0; icells()); } QStringList knownCells(iKnownCells.keys()); allCells.sort(); knownCells.sort(); if (allCells != knownCells) { QMap > bak(iKnownCells); iKnownCells.clear(); for (i=0; i cell = bak.value(path); if (cell.isNull()) { cell = QSharedPointer(new QOfonoExtCell(path), &QObject::deleteLater); } iKnownCells.insert(path, cell); if (!bak.remove(path)) { // This is the first time we are seeing this cell connect(cell.data(), SIGNAL(validChanged()), SLOT(updateValidCells())); } } // Disconnect those cells that we no longer need QList > leftover = bak.values(); for (i=0; idisconnect(this); } } return allCells; } void QOfonoExtCellWatcher::Private::updateValidCells() { QStringList knownCells = updateKnownCells(); QStringList validCells; int i; for (i=0; i cell = iKnownCells.value(path); if (cell->valid()) { validCells.append(path); } } bool changed = true; if (validCells.count() == iValidCells.count()) { changed = false; for (i=0; ipath() != validCells.at(i)) { changed = true; break; } } } if (changed && validCells.count() == knownCells.count()) { iValidCells.clear(); for (i=0; icellsChanged(); } } } QOfonoExtCellWatcher::QOfonoExtCellWatcher(QObject* aParent) : QObject(aParent), iPrivate(new Private(this)) { } QOfonoExtCellWatcher::~QOfonoExtCellWatcher() { iPrivate->iParent = NULL; iPrivate->deleteLater(); } QList > QOfonoExtCellWatcher::cells() const { return iPrivate->iValidCells; } #include "qofonoextcellwatcher.moc" libqofonoext-1.0.32/src/qofonoextcellwatcher.h000066400000000000000000000023231457630555700215270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTCELLWATCHER_H #define QOFONOEXTCELLWATCHER_H #include "qofonoextcell.h" // Watches available cells from all modems class QOFONOEXT_EXPORT QOfonoExtCellWatcher : public QObject { Q_OBJECT public: explicit QOfonoExtCellWatcher(QObject* aParent = NULL); ~QOfonoExtCellWatcher(); QList > cells() const; Q_SIGNALS: void cellsChanged(); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTCELLWATCHER_H libqofonoext-1.0.32/src/qofonoextmodemmanager.cpp000066400000000000000000000577251457630555700222410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2022 Jolla Ltd. ** Copyright (C) 2015-2022 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextmodemmanager.h" #include "qofonoext_p.h" // ========================================================================== // QOfonoExtModemManagerProxy // // qdbusxml2cpp doesn't really do much, and has a number of limitations, // such as the limits on number of arguments for QDBusPendingReply template. // It's easier to write these proxies by hand. // ========================================================================== class QOfonoExtModemManagerProxy: public QDBusAbstractInterface { Q_OBJECT public: class Error { public: Error() : iCount(0) {} public: QString iName; int iCount; }; QOfonoExtModemManagerProxy(QObject* aParent) : QDBusAbstractInterface(OFONO_SERVICE, "/", "org.nemomobile.ofono.ModemManager", OFONO_BUS, aParent), iInterfaceVersion(0) {} public Q_SLOTS: // METHODS QDBusPendingCall GetInterfaceVersion() { return asyncCall("GetInterfaceVersion"); } QDBusPendingCall GetAll() { return asyncCall("GetAll"); } QDBusPendingCall GetAll2() { return asyncCall("GetAll2"); } QDBusPendingCall GetAll3() { return asyncCall("GetAll3"); } QDBusPendingCall GetAll4() { return asyncCall("GetAll4"); } QDBusPendingCall GetAll5() { return asyncCall("GetAll5"); } QDBusPendingCall GetAll6() { return asyncCall("GetAll6"); } QDBusPendingCall GetAll7() { return asyncCall("GetAll7"); } QDBusPendingCall GetAll8() { return asyncCall("GetAll8"); } QDBusPendingCall SetDefaultDataSim(QString aImsi) { return asyncCall("SetDefaultDataSim", aImsi); } QDBusPendingCall SetDefaultVoiceSim(const QString &aImsi) { return asyncCall("SetDefaultVoiceSim", aImsi); } QDBusPendingCall SetEnabledModems(QList aModems) { return asyncCall("SetEnabledModems", QVariant::fromValue(aModems)); } Q_SIGNALS: // SIGNALS void DefaultDataModemChanged(QString aPath); void DefaultDataSimChanged(QString aImsi); void DefaultVoiceModemChanged(QString aPath); void DefaultVoiceSimChanged(QString aIimsi); void EnabledModemsChanged(QList aModems); void MmsModemChanged(QString aPath); void MmsSimChanged(QString aImsi); void PresentSimsChanged(int aIndex, bool aPresent); void ReadyChanged(bool aReady); void ModemError(QDBusObjectPath aModem, QString aName, QString aMessage); public: // Becomes non-zero after GetInterfaceVersion succeeds: int iInterfaceVersion; }; Q_DECLARE_METATYPE(QOfonoExtModemManagerProxy::Error) QDBusArgument& operator<<(QDBusArgument& aArg, const QOfonoExtModemManagerProxy::Error& aValue) { aArg.beginStructure(); aArg << aValue.iName; aArg << aValue.iCount; aArg.endStructure(); return aArg; } const QDBusArgument& operator>>(const QDBusArgument &aArg, QOfonoExtModemManagerProxy::Error& aValue) { aArg.beginStructure(); aArg >> aValue.iName; aArg >> aValue.iCount; aArg.endStructure(); return aArg; } // ========================================================================== // QOfonoExtModemManager::Private // ========================================================================== class QOfonoExtModemManager::Private : public QObject { Q_OBJECT typedef QList ErrorList; typedef QList ModemErrors; public: static QWeakPointer sSharedInstance; QOfonoExtModemManager* iParent; QOfonoExtModemManagerProxy* iProxy; QDBusPendingCallWatcher* iInitCall; QStringList iAvailableModems; QStringList iEnabledModems; QString iDefaultVoiceModem; QString iDefaultDataModem; QString iDefaultVoiceSim; QString iDefaultDataSim; QList iPresentSims; QStringList iIMEIs; QStringList iIMEISVs; QString iMmsSim; QString iMmsModem; int iPresentSimCount; int iActiveSimCount; int iInterfaceVersion; bool iReady; bool iValid; int iErrorCount; Private(QOfonoExtModemManager* aParent); static QStringList toStringList(QList aList); static QList toPathList(QStringList aList); QStringList dummyStringList(); void getAll(); void getInterfaceVersion(); void presentSimsChanged(QList aOldList); void updateSimCounts(); void updateEnabledModems(QStringList aModems); void updateDefaultDataModem(QString aPath); void updateDefaultVoiceModem(QString aPath); void updateDefaultDataSim(QString aImsi); void updateDefaultVoiceSim(QString aImsi); void updateMmsSim(QString aImsi); void updateMmsModem(QString aPath); void updateReady(bool aReady); private Q_SLOTS: void onServiceRegistered(); void onServiceUnregistered(); void onGetInterfaceVersionFinished(QDBusPendingCallWatcher* aWatcher); void onGetAllFinished(QDBusPendingCallWatcher* aWatcher); void onEnabledModemsChanged(QList aModems); void onDefaultVoiceModemChanged(QString aModemPath); void onDefaultDataModemChanged(QString aModemPath); void onDefaultVoiceSimChanged(QString aImsi); void onDefaultDataSimChanged(QString aImsi); void onPresentSimsChanged(int aIndex, bool aPresent); void onMmsSimChanged(QString aImsi); void onMmsModemChanged(QString aModemPath); void onReadyChanged(bool aReady); void onModemError(QDBusObjectPath aModem, QString aName, QString aMessage); }; QWeakPointer QOfonoExtModemManager::Private::sSharedInstance; QStringList QOfonoExtModemManager::Private::toStringList(QList aList) { QStringList stringList; const int n = aList.count(); for (int i=0; i QOfonoExtModemManager::Private::toPathList(QStringList aList) { QList pathList; const int n = aList.count(); for (int i=0; i("QOfonoExtModemManagerProxy::Error"); qDBusRegisterMetaType(); QDBusServiceWatcher* ofonoWatcher = new QDBusServiceWatcher(OFONO_SERVICE, OFONO_BUS, QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); connect(ofonoWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(onServiceRegistered())); connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(onServiceUnregistered())); if (OFONO_BUS.interface()->isServiceRegistered(OFONO_SERVICE)) { onServiceRegistered(); } } void QOfonoExtModemManager::Private::onServiceRegistered() { const bool wasValid = iValid; if (!iProxy) { iProxy = new QOfonoExtModemManagerProxy(this); if (iProxy->isValid()) { iValid = false; connect(iProxy, SIGNAL(EnabledModemsChanged(QList)), SLOT(onEnabledModemsChanged(QList))); connect(iProxy, SIGNAL(DefaultDataModemChanged(QString)), SLOT(onDefaultDataModemChanged(QString))); connect(iProxy, SIGNAL(DefaultVoiceModemChanged(QString)), SLOT(onDefaultVoiceModemChanged(QString))); connect(iProxy, SIGNAL(DefaultDataSimChanged(QString)), SLOT(onDefaultDataSimChanged(QString))); connect(iProxy, SIGNAL(DefaultVoiceSimChanged(QString)), SLOT(onDefaultVoiceSimChanged(QString))); connect(iProxy, SIGNAL(PresentSimsChanged(int,bool)), SLOT(onPresentSimsChanged(int,bool))); getInterfaceVersion(); } else { delete iProxy; iProxy = NULL; } } if (wasValid != iValid) { Q_EMIT iParent->validChanged(iValid); } } void QOfonoExtModemManager::Private::onServiceUnregistered() { if (iProxy) { // iProxy is the parent of iInitCall iInitCall = NULL; delete iProxy; iProxy = NULL; } if (iValid) { iValid = false; Q_EMIT iParent->validChanged(iValid); } } void QOfonoExtModemManager::Private::getInterfaceVersion() { iInitCall = new QDBusPendingCallWatcher(iProxy->GetInterfaceVersion(), iProxy); connect(iInitCall, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onGetInterfaceVersionFinished(QDBusPendingCallWatcher*))); } void QOfonoExtModemManager::Private::getAll() { iInitCall = new QDBusPendingCallWatcher( (iInterfaceVersion == 2) ? QDBusPendingCall(iProxy->GetAll2()) : (iInterfaceVersion == 3) ? QDBusPendingCall(iProxy->GetAll3()) : (iInterfaceVersion == 4) ? QDBusPendingCall(iProxy->GetAll4()) : (iInterfaceVersion == 5) ? QDBusPendingCall(iProxy->GetAll5()) : (iInterfaceVersion == 6) ? QDBusPendingCall(iProxy->GetAll6()) : (iInterfaceVersion == 7) ? QDBusPendingCall(iProxy->GetAll7()) : QDBusPendingCall(iProxy->GetAll8()), iProxy); connect(iInitCall, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onGetAllFinished(QDBusPendingCallWatcher*))); } void QOfonoExtModemManager::Private::onGetInterfaceVersionFinished(QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply reply(*aWatcher); iInitCall = NULL; if (reply.isError()) { // Repeat the call on timeout qWarning() << reply.error(); if (QOfonoExt::isTimeout(reply.error())) { getInterfaceVersion(); } } else { const int version = reply.value(); // Make sure we don't connect signals more than once if (version > iProxy->iInterfaceVersion) { if (version >= 4 && iProxy->iInterfaceVersion < 4) { connect(iProxy, SIGNAL(MmsSimChanged(QString)), SLOT(onMmsSimChanged(QString))); connect(iProxy, SIGNAL(MmsModemChanged(QString)), SLOT(onMmsModemChanged(QString))); } if (version >= 5 && iProxy->iInterfaceVersion < 5) { connect(iProxy, SIGNAL(ReadyChanged(bool)), SLOT(onReadyChanged(bool))); } if (version >= 6 && iProxy->iInterfaceVersion < 6) { connect(iProxy, SIGNAL(ModemError(QDBusObjectPath,QString,QString)), SLOT(onModemError(QDBusObjectPath,QString,QString))); } iProxy->iInterfaceVersion = version; } if (iInterfaceVersion != version) { iInterfaceVersion = version; iParent->interfaceVersionChanged(version); } getAll(); } aWatcher->deleteLater(); } void QOfonoExtModemManager::Private::onGetAllFinished(QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply, // AvailableModems QList, // EnabledModems QString, // DefaultDataSim QString, // DefaultVoiceSim QString, // DefaultDataModem QString, // DefaultVoiceModem QList > // PresentSims reply(*aWatcher); iInitCall = NULL; if (reply.isError()) { // Repeat the call on timeout qWarning() << reply.error(); if (QOfonoExt::isTimeout(reply.error())) { getAll(); } } else { const int version = reply.argumentAt<0>(); QStringList list = toStringList(reply.argumentAt<1>()); if (iAvailableModems != list) { iAvailableModems = list; Q_EMIT iParent->availableModemsChanged(iAvailableModems); } updateEnabledModems(toStringList(reply.argumentAt<2>())); updateDefaultDataSim(reply.argumentAt<3>()); updateDefaultVoiceSim(reply.argumentAt<4>()); updateDefaultDataModem(reply.argumentAt<5>()); updateDefaultVoiceModem(reply.argumentAt<6>()); QList oldList = iPresentSims; iPresentSims = reply.argumentAt<7>(); presentSimsChanged(oldList); if (version >= 3) { // 8: imei list = reply.argumentAt(8).toStringList(); } else { list = dummyStringList(); } if (iIMEIs != list) { iIMEIs = list; Q_EMIT iParent->imeiCodesChanged(iIMEIs); } if (version >= 4) { // 9: mmsSim // 10: mmsModem updateMmsSim(reply.argumentAt(9).toString()); updateMmsModem(reply.argumentAt(10).toString()); } if (version >= 5) { // 11: ready updateReady(reply.argumentAt(11).toBool()); } else { // Old ofono is always ready :) updateReady(true); } int errorCount = 0; if (version >= 6) { // 12: modemErrors ModemErrors me = qdbus_cast(reply.argumentAt(12)); const int n = me.count(); for (int i=0; i= 7) { // 13: imeisv list = reply.argumentAt(13).toStringList(); } else { list = dummyStringList(); } if (version >= 8) { // 14: errors ErrorList errors = qdbus_cast(reply.argumentAt(14)); const int k = errors.count(); for (int i=0; ierrorCountChanged(errorCount); } if (iIMEISVs != list) { iIMEISVs = list; Q_EMIT iParent->imeisvCodesChanged(iIMEISVs); } if (!iValid) { iValid = true; Q_EMIT iParent->validChanged(iValid); } } aWatcher->deleteLater(); } QStringList QOfonoExtModemManager::Private::dummyStringList() { QStringList list; const int n = iAvailableModems.count(); for (int i=0; i aOldList) { int i; const int n = iPresentSims.count(); QList changed; changed.reserve(n); for (i=0; ipresentSimChanged(i, iPresentSims.at(i)); } } if (aOldList != iPresentSims) { Q_EMIT iParent->presentSimsChanged(iPresentSims); } } void QOfonoExtModemManager::Private::updateSimCounts() { const int oldPresentSimCount = iPresentSimCount; const int oldActiveSimCount = iActiveSimCount; iPresentSimCount = 0; iActiveSimCount = 0; const int n = iPresentSims.count(); for (int i=0; ipresentSimCountChanged(iPresentSimCount); } if (oldActiveSimCount != iActiveSimCount) { Q_EMIT iParent->activeSimCountChanged(iActiveSimCount); } } void QOfonoExtModemManager::Private::updateEnabledModems(QStringList aModems) { if (iEnabledModems != aModems) { iEnabledModems = aModems; Q_EMIT iParent->enabledModemsChanged(aModems); } updateSimCounts(); } void QOfonoExtModemManager::Private::updateDefaultDataModem(QString aPath) { if (iDefaultDataModem != aPath) { iDefaultDataModem = aPath; Q_EMIT iParent->defaultDataModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateDefaultVoiceModem(QString aPath) { if (iDefaultVoiceModem != aPath) { iDefaultVoiceModem = aPath; Q_EMIT iParent->defaultVoiceModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateDefaultDataSim(QString aImsi) { if (iDefaultDataSim != aImsi) { iDefaultDataSim = aImsi; Q_EMIT iParent->defaultDataSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateDefaultVoiceSim(QString aImsi) { if (iDefaultVoiceSim != aImsi) { iDefaultVoiceSim = aImsi; Q_EMIT iParent->defaultVoiceSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateMmsSim(QString aImsi) { if (iMmsSim != aImsi) { iMmsSim = aImsi; Q_EMIT iParent->mmsSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateMmsModem(QString aPath) { if (iMmsModem != aPath) { iMmsModem = aPath; Q_EMIT iParent->mmsModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateReady(bool aReady) { if (iReady != aReady) { iReady = aReady; Q_EMIT iParent->readyChanged(aReady); } } void QOfonoExtModemManager::Private::onEnabledModemsChanged(QList aModems) { if (!iInitCall) { updateEnabledModems(toStringList(aModems)); } } void QOfonoExtModemManager::Private::onDefaultDataModemChanged(QString aPath) { if (!iInitCall) { updateDefaultDataModem(aPath); } } void QOfonoExtModemManager::Private::onDefaultVoiceModemChanged(QString aPath) { if (!iInitCall) { updateDefaultVoiceModem(aPath); } } void QOfonoExtModemManager::Private::onDefaultDataSimChanged(QString aImsi) { if (!iInitCall) { updateDefaultDataSim(aImsi); } } void QOfonoExtModemManager::Private::onDefaultVoiceSimChanged(QString aImsi) { if (!iInitCall) { updateDefaultVoiceSim(aImsi); } } void QOfonoExtModemManager::Private::onPresentSimsChanged(int aIndex, bool aPresent) { if (!iInitCall && aIndex >= 0 && aIndex < iPresentSims.count()) { QList oldList = iPresentSims; iPresentSims[aIndex] = aPresent; presentSimsChanged(oldList); } } void QOfonoExtModemManager::Private::onMmsSimChanged(QString aImsi) { if (!iInitCall) { updateMmsSim(aImsi); } } void QOfonoExtModemManager::Private::onMmsModemChanged(QString aPath) { if (!iInitCall) { updateMmsModem(aPath); } } void QOfonoExtModemManager::Private::onReadyChanged(bool aReady) { if (!iInitCall) { updateReady(aReady); } } void QOfonoExtModemManager::Private::onModemError(QDBusObjectPath aPath, QString aName, QString aMessage) { if (!iInitCall) { iErrorCount++; Q_EMIT iParent->errorCountChanged(iErrorCount); Q_EMIT iParent->modemError(aPath.path(), aName, aMessage); } } // ========================================================================== // QOfonoExtModemManager // ========================================================================== QOfonoExtModemManager::QOfonoExtModemManager(QObject* aParent) : QObject(aParent), iPrivate(new Private(this)) { } QOfonoExtModemManager::~QOfonoExtModemManager() { } bool QOfonoExtModemManager::valid() const { return iPrivate->iValid; } int QOfonoExtModemManager::interfaceVersion() const { return iPrivate->iInterfaceVersion; } QStringList QOfonoExtModemManager::availableModems() const { return iPrivate->iAvailableModems; } QStringList QOfonoExtModemManager::enabledModems() const { return iPrivate->iEnabledModems; } QString QOfonoExtModemManager::defaultVoiceModem() const { return iPrivate->iDefaultVoiceModem; } QString QOfonoExtModemManager::defaultDataModem() const { return iPrivate->iDefaultDataModem; } QString QOfonoExtModemManager::defaultVoiceSim() const { return iPrivate->iDefaultVoiceSim; } QString QOfonoExtModemManager::defaultDataSim() const { return iPrivate->iDefaultDataSim; } QList QOfonoExtModemManager::presentSims() const { return iPrivate->iPresentSims; } QStringList QOfonoExtModemManager::imeiCodes() const { return iPrivate->iIMEIs; } QStringList QOfonoExtModemManager::imeisvCodes() const { return iPrivate->iIMEISVs; } QString QOfonoExtModemManager::mmsSim() const { return iPrivate->iMmsSim; } QString QOfonoExtModemManager::mmsModem() const { return iPrivate->iMmsModem; } bool QOfonoExtModemManager::ready() const { return iPrivate->iReady; } int QOfonoExtModemManager::presentSimCount() const { return iPrivate->iPresentSimCount; } int QOfonoExtModemManager::activeSimCount() const { return iPrivate->iActiveSimCount; } int QOfonoExtModemManager::errorCount() const { return iPrivate->iErrorCount; } QString QOfonoExtModemManager::imeiAt(int aIndex) const { if (aIndex >= 0 && aIndex < iPrivate->iIMEIs.count()) { return iPrivate->iIMEIs.at(aIndex); } else { return QString(); } } QString QOfonoExtModemManager::imeisvAt(int aIndex) const { if (aIndex >= 0 && aIndex < iPrivate->iIMEISVs.count()) { return iPrivate->iIMEISVs.at(aIndex); } else { return QString(); } } bool QOfonoExtModemManager::simPresentAt(int aIndex) const { if (aIndex >= 0 && aIndex < iPrivate->iPresentSims.count()) { return iPrivate->iPresentSims.at(aIndex); } else { return false; } } void QOfonoExtModemManager::setEnabledModems(QStringList aModems) { if (iPrivate->iProxy) { iPrivate->iProxy->SetEnabledModems(Private::toPathList(aModems)); } // Optimistically cache the changes if (iPrivate->iEnabledModems != aModems) { iPrivate->iEnabledModems = aModems; Q_EMIT enabledModemsChanged(aModems); } } void QOfonoExtModemManager::setDefaultDataSim(QString aImsi) { if (iPrivate->iProxy) { iPrivate->iProxy->SetDefaultDataSim(aImsi); } // Optimistically cache the changes if (iPrivate->iDefaultDataSim != aImsi) { iPrivate->iDefaultDataSim = aImsi; Q_EMIT defaultDataSimChanged(aImsi); } } void QOfonoExtModemManager::setDefaultVoiceSim(QString aImsi) { if (iPrivate->iProxy) { iPrivate->iProxy->SetDefaultVoiceSim(aImsi); } // Optimistically cache the changes if (iPrivate->iDefaultVoiceSim != aImsi) { iPrivate->iDefaultVoiceSim = aImsi; Q_EMIT defaultVoiceSimChanged(aImsi); } } QSharedPointer QOfonoExtModemManager::instance() { QSharedPointer instance = Private::sSharedInstance; if (instance.isNull()) { instance = QSharedPointer::create(); Private::sSharedInstance = instance; } return instance; } #include "qofonoextmodemmanager.moc" libqofonoext-1.0.32/src/qofonoextmodemmanager.h000066400000000000000000000104451457630555700216720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTMODEMMANAGER_H #define QOFONOEXTMODEMMANAGER_H #include "qofonoext_types.h" class QOFONOEXT_EXPORT QOfonoExtModemManager : public QObject { Q_OBJECT Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(int interfaceVersion READ interfaceVersion NOTIFY interfaceVersionChanged) Q_PROPERTY(QStringList availableModems READ availableModems NOTIFY availableModemsChanged) Q_PROPERTY(QStringList enabledModems READ enabledModems WRITE setEnabledModems NOTIFY enabledModemsChanged) Q_PROPERTY(QString defaultDataModem READ defaultDataModem NOTIFY defaultDataModemChanged) Q_PROPERTY(QString defaultVoiceModem READ defaultVoiceModem NOTIFY defaultVoiceModemChanged) Q_PROPERTY(QString defaultDataSim READ defaultDataSim WRITE setDefaultDataSim NOTIFY defaultDataSimChanged) Q_PROPERTY(QString defaultVoiceSim READ defaultVoiceSim WRITE setDefaultVoiceSim NOTIFY defaultVoiceSimChanged) Q_PROPERTY(QList presentSims READ presentSims NOTIFY presentSimsChanged) Q_PROPERTY(QStringList imeiCodes READ imeiCodes NOTIFY imeiCodesChanged) Q_PROPERTY(QStringList imeisvCodes READ imeisvCodes NOTIFY imeisvCodesChanged) Q_PROPERTY(QString mmsSim READ mmsSim NOTIFY mmsSimChanged) Q_PROPERTY(QString mmsModem READ mmsModem NOTIFY mmsModemChanged) Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) Q_PROPERTY(int presentSimCount READ presentSimCount NOTIFY presentSimCountChanged) Q_PROPERTY(int activeSimCount READ activeSimCount NOTIFY activeSimCountChanged) Q_PROPERTY(int errorCount READ errorCount NOTIFY errorCountChanged) public: explicit QOfonoExtModemManager(QObject *parent = nullptr); ~QOfonoExtModemManager(); bool valid() const; int interfaceVersion() const; QStringList availableModems() const; QStringList enabledModems() const; QString defaultDataModem() const; QString defaultVoiceModem() const; QString defaultDataSim() const; QString defaultVoiceSim() const; QList presentSims() const; QStringList imeiCodes() const; QStringList imeisvCodes() const; QString mmsSim() const; QString mmsModem() const; bool ready() const; int presentSimCount() const; int activeSimCount() const; int errorCount() const; Q_INVOKABLE QString imeiAt(int aIndex) const; Q_INVOKABLE QString imeisvAt(int aIndex) const; Q_INVOKABLE bool simPresentAt(int aIndex) const; void setEnabledModems(QStringList aModems); void setDefaultDataSim(QString aImsi); void setDefaultVoiceSim(QString aImsi); static QSharedPointer instance(); Q_SIGNALS: void validChanged(bool value); void interfaceVersionChanged(int value); void availableModemsChanged(QStringList value); void enabledModemsChanged(QStringList value); void defaultVoiceModemChanged(QString value); void defaultDataModemChanged(QString value); void defaultVoiceSimChanged(QString value); void defaultDataSimChanged(QString value); void presentSimsChanged(QList value); void presentSimChanged(int index, bool present); void presentSimCountChanged(int value); void activeSimCountChanged(int value); void imeiCodesChanged(QStringList value); void imeisvCodesChanged(QStringList value); void mmsSimChanged(QString value); void mmsModemChanged(QString value); void readyChanged(bool value); void errorCountChanged(int value); void modemError(QString modemPath, QString errorId, QString errorMessage); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTMODEMMANAGER_H libqofonoext-1.0.32/src/qofonoextsiminfo.cpp000066400000000000000000000175631457630555700212450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #include "qofonoextsiminfo.h" #include "qofonoext_p.h" #include // ========================================================================== // QOfonoExtSimInfoProxy // // qdbusxml2cpp doesn't really do much, and has a number of limitations, // such as the limits on number of arguments for QDBusPendingReply template. // It's easier to write these proxies by hand. // ========================================================================== class QOfonoExtSimInfoProxy: public QDBusAbstractInterface { Q_OBJECT public: static const QString INTERFACE; QOfonoExtSimInfoProxy(QString aPath, QObject* aParent) : QDBusAbstractInterface(OFONO_SERVICE, aPath, qPrintable(INTERFACE), OFONO_BUS, aParent) {} public Q_SLOTS: // METHODS QDBusPendingCall GetInterfaceVersion() { return asyncCall("GetInterfaceVersion"); } QDBusPendingCall GetAll() { return asyncCall("GetAll"); } Q_SIGNALS: // SIGNALS void CardIdentifierChanged(QString aIccid); void ServiceProviderNameChanged(QString aSpn); void SubscriberIdentityChanged(QString aImsi); }; const QString QOfonoExtSimInfoProxy::INTERFACE("org.nemomobile.ofono.SimInfo"); // ========================================================================== // QOfonoExtSimInfo::Private // ========================================================================== class QOfonoExtSimInfo::Private : public QObject { Q_OBJECT public: QOfonoExtSimInfo* iParent; QOfonoExtSimInfoProxy* iProxy; QSharedPointer iModem; bool iValid; QString iModemPath; QString iCardIdentifier; QString iSubscriberIdentity; QString iServiceProviderName; Private(QOfonoExtSimInfo* aParent); QString modemPath() const; void setModemPath(QString aPath); void invalidate(); void getAll(); private Q_SLOTS: void checkInterfacePresence(); void onGetAllFinished(QDBusPendingCallWatcher* aWatcher); void onCardIdentifierChanged(QString aCardIdentifier); void onSubscriberIdentityChanged(QString aSubscriberIdentity); void onServiceProviderNameChanged(QString aServiceProviderName); }; QOfonoExtSimInfo::Private::Private(QOfonoExtSimInfo* aParent) : QObject(aParent), iParent(aParent), iProxy(NULL), iValid(false) { } QString QOfonoExtSimInfo::Private::modemPath() const { return iModem.isNull() ? QString() : iModem->objectPath(); } void QOfonoExtSimInfo::Private::setModemPath(QString aPath) { if (aPath != modemPath()) { invalidate(); if (aPath.isEmpty()) { iModem.clear(); } else { if (iModem) iModem->disconnect(this); iModem = QOfonoModem::instance(aPath); connect(iModem.data(), SIGNAL(validChanged(bool)), SLOT(checkInterfacePresence())); connect(iModem.data(), SIGNAL(interfacesChanged(QStringList)), SLOT(checkInterfacePresence())); checkInterfacePresence(); } iParent->modemPathChanged(modemPath()); } } void QOfonoExtSimInfo::Private::checkInterfacePresence() { if (iModem && iModem->isValid() && iModem->interfaces().contains(QOfonoExtSimInfoProxy::INTERFACE)) { if (!iProxy) { iProxy = new QOfonoExtSimInfoProxy(iModem->objectPath(), this); if (iProxy->isValid()) { connect(iProxy, SIGNAL(CardIdentifierChanged(QString)), SLOT(onCardIdentifierChanged(QString))); connect(iProxy, SIGNAL(SubscriberIdentityChanged(QString)), SLOT(onSubscriberIdentityChanged(QString))); connect(iProxy, SIGNAL(ServiceProviderNameChanged(QString)), SLOT(onServiceProviderNameChanged(QString))); getAll(); } else { invalidate(); } } } else { invalidate(); } } void QOfonoExtSimInfo::Private::invalidate() { if (iProxy) { delete iProxy; iProxy = NULL; } if (iValid) { iValid = false; Q_EMIT iParent->validChanged(false); } } void QOfonoExtSimInfo::Private::getAll() { connect(new QDBusPendingCallWatcher(iProxy->GetAll(), iProxy), SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onGetAllFinished(QDBusPendingCallWatcher*))); } void QOfonoExtSimInfo::Private::onGetAllFinished(QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply // ServiceProviderName reply(*aWatcher); if (reply.isError()) { // Repeat the call on timeout qWarning() << reply.error(); if (QOfonoExt::isTimeout(reply.error())) { getAll(); } } else { QString iccid = reply.argumentAt<1>(); if (iCardIdentifier != iccid) { iCardIdentifier = iccid; Q_EMIT iParent->cardIdentifierChanged(iccid); } QString imsi = reply.argumentAt<2>(); if (iSubscriberIdentity != imsi) { iSubscriberIdentity = imsi; Q_EMIT iParent->subscriberIdentityChanged(imsi); } QString spn = reply.argumentAt<3>(); if (iServiceProviderName != spn) { iServiceProviderName = spn; Q_EMIT iParent->serviceProviderNameChanged(spn); } if (!iValid) { iValid = true; Q_EMIT iParent->validChanged(iValid); } } aWatcher->deleteLater(); } void QOfonoExtSimInfo::Private::onCardIdentifierChanged(QString aValue) { if (iCardIdentifier != aValue) { iCardIdentifier = aValue; Q_EMIT iParent->cardIdentifierChanged(aValue); } } void QOfonoExtSimInfo::Private::onSubscriberIdentityChanged(QString aValue) { if (iSubscriberIdentity != aValue) { iSubscriberIdentity = aValue; Q_EMIT iParent->subscriberIdentityChanged(aValue); } } void QOfonoExtSimInfo::Private::onServiceProviderNameChanged(QString aValue) { if (iServiceProviderName != aValue) { iServiceProviderName = aValue; Q_EMIT iParent->serviceProviderNameChanged(aValue); } } // ========================================================================== // QOfonoExtSimInfo // ========================================================================== QOfonoExtSimInfo::QOfonoExtSimInfo(QObject* aParent) : QObject(aParent), iPrivate(new Private(this)) { } QOfonoExtSimInfo::~QOfonoExtSimInfo() { } bool QOfonoExtSimInfo::valid() const { return iPrivate->iValid; } QString QOfonoExtSimInfo::modemPath() const { return iPrivate->modemPath(); } QString QOfonoExtSimInfo::cardIdentifier() const { return iPrivate->iCardIdentifier; } QString QOfonoExtSimInfo::subscriberIdentity() const { return iPrivate->iSubscriberIdentity; } QString QOfonoExtSimInfo::serviceProviderName() const { return iPrivate->iServiceProviderName; } void QOfonoExtSimInfo::setModemPath(QString aPath) { iPrivate->setModemPath(aPath); } #include "qofonoextsiminfo.moc" libqofonoext-1.0.32/src/qofonoextsiminfo.h000066400000000000000000000036571457630555700207110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015-2021 Jolla Ltd. ** Copyright (C) 2015-2021 Slava Monich ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ #ifndef QOFONOEXTSIMINFO_H #define QOFONOEXTSIMINFO_H #include "qofonoext_types.h" class QOFONOEXT_EXPORT QOfonoExtSimInfo : public QObject { Q_OBJECT Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(QString modemPath READ modemPath WRITE setModemPath NOTIFY modemPathChanged) Q_PROPERTY(QString cardIdentifier READ cardIdentifier NOTIFY cardIdentifierChanged) Q_PROPERTY(QString subscriberIdentity READ subscriberIdentity NOTIFY subscriberIdentityChanged) Q_PROPERTY(QString serviceProviderName READ serviceProviderName NOTIFY serviceProviderNameChanged) public: explicit QOfonoExtSimInfo(QObject* aParent = NULL); ~QOfonoExtSimInfo(); bool valid() const; QString modemPath() const; QString cardIdentifier() const; QString subscriberIdentity() const; QString serviceProviderName() const; void setModemPath(QString aPath); Q_SIGNALS: void validChanged(bool value); void modemPathChanged(QString value); void cardIdentifierChanged(QString value); void subscriberIdentityChanged(QString value); void serviceProviderNameChanged(QString value); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTSIMINFO_H libqofonoext-1.0.32/src/src.pro000066400000000000000000000023311457630555700164260ustar00rootroot00000000000000TARGET = qofonoext CONFIG += create_pc create_prl no_install_prl link_pkgconfig PKGCONFIG += qofono-qt$${QT_MAJOR_VERSION} QT += dbus QT -= gui QMAKE_CXXFLAGS += -Wno-unused-parameter -Wno-psabi include(version.pri) TEMPLATE = lib DEFINES += QOFONOEXT_LIBRARY isEmpty(PREFIX) { PREFIX=/usr } OTHER_FILES += \ qofonoext.prf \ version.pri SOURCES += \ qofonoext.cpp \ qofonoextcell.cpp \ qofonoextcellinfo.cpp \ qofonoextcellwatcher.cpp \ qofonoextmodemmanager.cpp \ qofonoextsiminfo.cpp PUBLIC_HEADERS += \ qofonoextcell.h \ qofonoextcellinfo.h \ qofonoextcellwatcher.h \ qofonoextmodemmanager.h \ qofonoextsiminfo.h \ qofonoext_types.h HEADERS += \ $$PUBLIC_HEADERS \ qofonoext_p.h target.path = $$[QT_INSTALL_LIBS] headers.files = $$PUBLIC_HEADERS headers.path = $$INSTALL_ROOT$$PREFIX/include/qofonoext pkgconfig.files = qofonoext.pc pkgconfig.path = $$[QT_INSTALL_LIBS]/pkgconfig QMAKE_PKGCONFIG_NAME = $$TARGET QMAKE_PKGCONFIG_DESTDIR = pkgconfig QMAKE_PKGCONFIG_INCDIR = $$headers.path QMAKE_PKGCONFIG_DESCRIPTION = Qt bindings for ofono extensions QMAKE_PKGCONFIG_PREFIX = $$PREFIX QMAKE_PKGCONFIG_VERSION = $$VERSION INSTALLS += target headers pkgconfig libqofonoext-1.0.32/src/version.pri000066400000000000000000000000211457630555700173100ustar00rootroot00000000000000VERSION = 1.0.31