pax_global_header00006660000000000000000000000064152440657210014520gustar00rootroot0000000000000052 comment=4049edd4d4b11f14d047b6a7b2a7c16b8b0c3476 libqofonoext-1.2.0/000077500000000000000000000000001524406572100142315ustar00rootroot00000000000000libqofonoext-1.2.0/.gitignore000066400000000000000000000003251524406572100162210ustar00rootroot00000000000000*~ build .DS_Store *.pro.user .qmake.stash Makefile CMakeLists.txt.user* plugin/Makefile plugin/libqofonoextdeclarative*.so* src/Makefile src/libqofonoext*.prl src/libqofonoext*.so* src/pkgconfig/ moc_* *.o *.moc libqofonoext-1.2.0/CMakeLists.txt000066400000000000000000000030651524406572100167750ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.12.0 FATAL_ERROR) set(LIBQOFONOEXT_VERSION "1.2.0" CACHE STRING "libqofonoext version") set(QT_MAJOR_VERSION 5 CACHE STRING "Qt major version") project(libqofonoext VERSION ${LIBQOFONOEXT_VERSION} DESCRIPTION "Library for accessing Sailfish OS specific ofono extensions" HOMEPAGE_URL "https://github.com/sailfishos/libqofonoext" LANGUAGES CXX ) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(GNUInstallDirs) include(FeatureSummary) find_package(PkgConfig) pkg_check_modules(QOFONO_QT REQUIRED qofono-qt${QT_MAJOR_VERSION}) find_package(Qt${QT_MAJOR_VERSION} COMPONENTS DBus Qml) set_package_properties(Qt${QT_MAJOR_VERSION} PROPERTIES TYPE REQUIRED DESCRIPTION "Qt${QT_MAJOR_VERSION} libraries" URL "https://www.qt.io" ) SET(QTDBUS_LIB Qt${QT_MAJOR_VERSION}::DBus) SET(QTQML_LIB Qt${QT_MAJOR_VERSION}::Qml) set_package_properties(PkgConfig PROPERTIES TYPE REQUIRED DESCRIPTION "Helper tool for compiling applications and libraries" URL "https://www.freedesktop.org/wiki/Software/pkg-config/" ) set_package_properties(QOFONO_QT PROPERTIES TYPE REQUIRED DESCRIPTION "Library for accessing the ofono daemon" URL "https://github.com/sailfishos/libqofono" ) feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) if(QT_MAJOR_VERSION STREQUAL "6") set(QTVERSION_SUFFIX "-qt6") else() SET(QTVERSION_SUFFIX "") endif() add_subdirectory(src) add_subdirectory(plugin) libqofonoext-1.2.0/LICENSE.LGPL000066400000000000000000000011531524406572100157730ustar00rootroot00000000000000Copyright (C) 2026 Jolla Mobile Ltd Copyright (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.2.0/README000066400000000000000000000001671524406572100151150ustar00rootroot00000000000000qofono-ext ========== A library for accessing Sailfish OS specific ofono extensions, and a declarative plugin for it. libqofonoext-1.2.0/plugin/000077500000000000000000000000001524406572100155275ustar00rootroot00000000000000libqofonoext-1.2.0/plugin/CMakeLists.txt000066400000000000000000000026651524406572100203000ustar00rootroot00000000000000project(qofonoextdeclarative LANGUAGES CXX) set(PLUGIN_SOURCES qofonoextdeclarativeplugin.cpp qofonoextmodemlistmodel.cpp qofonoextsimlistmodel.cpp ) add_library(qofonoextdeclarative SHARED ${PLUGIN_SOURCES}) target_include_directories(qofonoextdeclarative PRIVATE ${CMAKE_SOURCE_DIR}/src ${QOFONO_QT_INCLUDE_DIRS} ) target_link_libraries(qofonoextdeclarative PRIVATE ${QTQML_LIB} ${QTDBUS_LIB} qofonoext${QTVERSION_SUFFIX} ${QOFONO_QT_LIBRARIES} ) # Set the output directory for the plugin and copy the qmldir file # to the appropriate location for qmlplugindump to find it. set_target_properties(qofonoextdeclarative PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/org/nemomobile/ofono ) configure_file(qmldir ${CMAKE_CURRENT_BINARY_DIR}/org/nemomobile/ofono/qmldir COPYONLY) # qmlplugindump is deprecated in Qt 6, qmltyperegistrar should be used # by the build system instead using QML_ELEMENT macros to declare the # types in the plugin. if(QT_MAJOR_VERSION STREQUAL "5") add_custom_target(qmltypes COMMAND qmlplugindump -nonrelocatable org.nemomobile.ofono 1.0 > ${CMAKE_CURRENT_SOURCE_DIR}/plugins.qmltypes ) endif() install(TARGETS qofonoextdeclarative LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt${QT_MAJOR_VERSION}/qml/org/nemomobile/ofono ) install(FILES qmldir plugins.qmltypes DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt${QT_MAJOR_VERSION}/qml/org/nemomobile/ofono )libqofonoext-1.2.0/plugin/plugins.qmltypes000066400000000000000000000245721524406572100210220ustar00rootroot00000000000000import 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 { type: "int" } } Method { name: "imeisvAt" type: "string" Parameter { type: "int" } } Method { name: "simPresentAt" type: "bool" Parameter { 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 } Property { name: "cardLabel"; type: "string" } 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" } } Signal { name: "cardLabelChanged" 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.2.0/plugin/qmldir000066400000000000000000000001221524406572100167350ustar00rootroot00000000000000module org.nemomobile.ofono plugin qofonoextdeclarative typeinfo plugins.qmltypes libqofonoext-1.2.0/plugin/qofonoextdeclarativeplugin.cpp000066400000000000000000000035041524406572100237020ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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 /* static */ void QOfonoExtDeclarativePlugin::registerTypes( const char* aUri, int aMajor, int aMinor) { 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) { Q_ASSERT(QLatin1String(aUri) == "org.nemomobile.ofono"); registerTypes(aUri, 1, 0); } libqofonoext-1.2.0/plugin/qofonoextdeclarativeplugin.h000066400000000000000000000023421524406572100233460ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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* uri) Q_DECL_OVERRIDE; static void registerTypes(const char* uri, int major, int minor); }; #endif // QOFONOEXTDECLARATIVEPLUGIN_H libqofonoext-1.2.0/plugin/qofonoextmodemlistmodel.cpp000066400000000000000000000175131524406572100232230ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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()) { QOfonoExtModemManager* mm = iModemManager.data(); connect(mm, &QOfonoExtModemManager::validChanged, this, &QOfonoExtModemListModel::onValidChanged); connect(mm, &QOfonoExtModemManager::availableModemsChanged, this, &QOfonoExtModemListModel::onAvailableModemsChanged); connect(mm, &QOfonoExtModemManager::enabledModemsChanged, this, &QOfonoExtModemListModel::onEnabledModemsChanged); connect(mm, &QOfonoExtModemManager::defaultDataModemChanged, this, &QOfonoExtModemListModel::onDefaultDataModemChanged); connect(mm, &QOfonoExtModemManager::defaultVoiceModemChanged, this, &QOfonoExtModemListModel::onDefaultVoiceModemChanged); connect(mm, &QOfonoExtModemManager::presentSimChanged, this, &QOfonoExtModemListModel::onPresentSimChanged); connect(mm, &QOfonoExtModemManager::imeiCodesChanged, this, &QOfonoExtModemListModel::onImeiCodesChanged); connect(mm, &QOfonoExtModemManager::imeisvCodesChanged, this, &QOfonoExtModemListModel::onImeisvCodesChanged); } 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&) 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( const QStringList& aModems) { const bool countHasChanged = iAvailableModems.count() != aModems.count(); beginResetModel(); iAvailableModems = aModems; endResetModel(); if (countHasChanged) { Q_EMIT countChanged(iAvailableModems.count()); } } void QOfonoExtModemListModel::onEnabledModemsChanged( const QStringList& aModems) { if (iEnabledModems != aModems) { const QStringList prevModems(iEnabledModems); const int n = iAvailableModems.count(); QVector role; role.append(EnabledRole); iEnabledModems = aModems; for (int i = 0; i < n; i++) { const QString& path(iAvailableModems.at(i)); if (prevModems.contains(path) != aModems.contains(path)) { QModelIndex index(createIndex(i, 0)); Q_EMIT dataChanged(index, index, role); } } } } void QOfonoExtModemListModel::onDefaultDataModemChanged( QString aModemPath) { const int prevIndex = iAvailableModems.indexOf(iDefaultDataModem); iDefaultDataModem = aModemPath; defaultModemChanged(DefaultDataRole, prevIndex, iAvailableModems.indexOf(aModemPath)); } void QOfonoExtModemListModel::onDefaultVoiceModemChanged( QString aModemPath) { const int prevIndex = iAvailableModems.indexOf(iDefaultVoiceModem); iDefaultVoiceModem = aModemPath; defaultModemChanged(DefaultVoiceRole, prevIndex, iAvailableModems.indexOf(aModemPath)); } void QOfonoExtModemListModel::onPresentSimChanged( int aIndex, bool aPresent) { const QModelIndex index(createIndex(aIndex, 0)); QVector role; role.append(SimPresentRole); 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( const QStringList& aList) { const QStringList prev(iImeiList); iImeiList = aList; roleChanged(IMEIRole, prev, aList); } void QOfonoExtModemListModel::onImeisvCodesChanged( const QStringList& aList) { const QStringList prev(iImeisvList); iImeisvList = aList; roleChanged(IMEISVRole, prev, aList); } void QOfonoExtModemListModel::roleChanged( Role aRole, const QStringList& aPrevList, const 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 < n; i++) { if (aPrevList.at(i) != aNewList.at(i)) { const QModelIndex index(createIndex(i, 0)); Q_EMIT dataChanged(index, index, role); } } } libqofonoext-1.2.0/plugin/qofonoextmodemlistmodel.h000066400000000000000000000050351524406572100226640ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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 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* parent = Q_NULLPTR); bool valid() const; int count() const; QHash roleNames() const Q_DECL_OVERRIDE; int rowCount(const QModelIndex&) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex&, int) const Q_DECL_OVERRIDE; bool setData(const QModelIndex&, const QVariant&, int) Q_DECL_OVERRIDE; Q_SIGNALS: void validChanged(bool aValid); void countChanged(int aCount); private Q_SLOTS: void onValidChanged(bool aValid); void onAvailableModemsChanged(const QStringList&); void onEnabledModemsChanged(const QStringList&); void onDefaultDataModemChanged(QString); void onDefaultVoiceModemChanged(QString); void onPresentSimChanged(int, bool); void onImeiCodesChanged(const QStringList&); void onImeisvCodesChanged(const QStringList&); private: void defaultModemChanged(Role, int, int); void roleChanged(Role aRole, const QStringList&, const QStringList&); private: QSharedPointer iModemManager; QStringList iAvailableModems; QStringList iEnabledModems; QString iDefaultVoiceModem; QString iDefaultDataModem; QStringList iImeiList; QStringList iImeisvList; }; #endif // QOFONOEXTMODEMLISTMODEL_H libqofonoext-1.2.0/plugin/qofonoextsimlistmodel.cpp000066400000000000000000000264301524406572100227100ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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 { friend class QOfonoExtSimListModel; Q_OBJECT public: SimData(QOfonoExtSimListModel*, QSharedPointer, QOfonoSimManager::SharedPointer, int index = -1); private: // SLOTS template void propertyChanged(); void onValidChanged(); void onCardLabelChanged(); private: QOfonoExtSimListModel* parentModel() const; bool isValid() const; int slotNumber() const; public: 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), 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, &QOfonoExtSimInfo::validChanged, this, &SimData::onValidChanged); connect(iCache, &QOfonoExtSimInfo::subscriberIdentityChanged, this, &SimData::propertyChanged); connect(iCache, &QOfonoExtSimInfo::serviceProviderNameChanged, this, &SimData::propertyChanged); connect(iCache, &QOfonoExtSimInfo::cardLabelChanged, this, &SimData::propertyChanged); connect(iModemManager.data(), &QOfonoExtModemManager::validChanged, this, &SimData::onValidChanged); connect(sim, &QOfonoSimManager::mobileCountryCodeChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::mobileNetworkCodeChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::subscriberNumbersChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::serviceNumbersChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::pinRequiredChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::lockedPinsChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::cardIdentifierChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::preferredLanguagesChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::pinRetriesChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::fixedDialingChanged, this, &SimData::propertyChanged); connect(sim, &QOfonoSimManager::barredDialingChanged, this, &SimData::propertyChanged); } QOfonoExtSimListModel* QOfonoExtSimListModel::SimData::parentModel() const { return qobject_cast(parent()); } template void QOfonoExtSimListModel::SimData::propertyChanged() { if (iIndex >= 0) { QOfonoExtSimListModel* model = parentModel(); const QModelIndex modelIndex(model->index(iIndex)); QVector roles; roles.append(role); Q_EMIT model->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(); } } if (iValid != valid) { iValid = valid; propertyChanged(); parentModel()->checkValid(); } } // ========================================================================== // 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 < sims.count(); i++) { iSimList.append(new SimData(this, iModemManager, sims.at(i), i)); } iValid = isValid(); connect(iSimWatcher, &QOfonoSimWatcher::validChanged, this, &QOfonoExtSimListModel::onPresentSimListChanged); connect(iSimWatcher, &QOfonoSimWatcher::presentSimListChanged, this, &QOfonoExtSimListModel::onPresentSimListChanged); } bool QOfonoExtSimListModel::valid() const { return iValid; } int QOfonoExtSimListModel::count() const { return iSimList.count(); } Qt::ItemFlags QOfonoExtSimListModel::flags( const QModelIndex& aIndex) const { return QAbstractListModel::flags(aIndex) | Qt::ItemIsEditable; } QHash 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"; roles[LabelRole] = "label"; 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(); case LabelRole: return d->iCache->cardLabel(); } } else { qWarning() << aIndex << aRole; } return QVariant(); } bool QOfonoExtSimListModel::setData( const QModelIndex& aIndex, const QVariant& aValue, int aRole) { const int row = aIndex.row(); if (row >= 0 && row < iSimList.count()) { if (aRole == LabelRole) { const SimData* d = iSimList.at(row); d->iCache->setCardLabel(aValue.toString()); return true; } } return QAbstractListModel::setData(aIndex, aValue, aRole); } 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; paths.reserve(sims.count()); for (i = 0; i < sims.count(); i++) { paths.append(sims.at(i)->modemPath()); } // 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; i < sims.count(); i++) { if (iSimList.count() <= i || iSimList.at(i)->iSim->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 && i < iSimList.count(); i++) { if (!iSimList.at(i)->iValid) { valid = false; } } return valid; } void QOfonoExtSimListModel::checkValid() { const bool wasValid = iValid; iValid = isValid(); if (iValid != wasValid) { Q_EMIT validChanged(); } } #include "qofonoextsimlistmodel.moc" libqofonoext-1.2.0/plugin/qofonoextsimlistmodel.h000066400000000000000000000050301524406572100223460ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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, LabelRole // Since 1.2.0 }; explicit QOfonoExtSimListModel(QObject* parent = Q_NULLPTR); bool valid() const; int count() const; protected: Qt::ItemFlags flags(const QModelIndex&) const Q_DECL_OVERRIDE; QHash roleNames() const Q_DECL_OVERRIDE; int rowCount(const QModelIndex&) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex&, int) const Q_DECL_OVERRIDE; bool setData(const QModelIndex&, const QVariant&, int) Q_DECL_OVERRIDE; 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.2.0/rpm/000077500000000000000000000000001524406572100150275ustar00rootroot00000000000000libqofonoext-1.2.0/rpm/libqofonoext-qt6.spec000066400000000000000000000030161524406572100211240ustar00rootroot00000000000000Name: libqofonoext-qt6 Summary: A library of Qt bindings for ofono extensions Version: 1.2.0 Release: 1 License: LGPLv2 URL: https://github.com/sailfishos/libqofonoext Source0: %{name}-%{version}.tar.bz2 %define libqofono_version 0.101 BuildRequires: cmake BuildRequires: pkgconfig BuildRequires: pkgconfig(Qt6Core) BuildRequires: pkgconfig(Qt6DBus) BuildRequires: pkgconfig(Qt6Quick) BuildRequires: pkgconfig(qofono-qt6) >= %{libqofono_version} Requires: libqofono-qt6 >= %{libqofono_version} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %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 %cmake . -DLIBQOFONOEXT_VERSION=$(sed 's/+.*//' <<<"%{version}") -DQT_MAJOR_VERSION=6 %cmake_build %install %cmake_install %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %{_libdir}/%{name}.so.* %license LICENSE.LGPL %files declarative %{_libdir}/qt6/qml/org/nemomobile/ofono %files devel %{_libdir}/%{name}.so %{_libdir}/pkgconfig/qofonoext-qt6.pc %{_includedir}/qofonoext-qt6/*.h libqofonoext-1.2.0/rpm/libqofonoext.spec000066400000000000000000000035071524406572100204210ustar00rootroot00000000000000Name: libqofonoext Summary: A library of Qt bindings for ofono extensions Version: 1.2.0 Release: 1 License: LGPLv2 URL: https://github.com/sailfishos/libqofonoext Source0: %{name}-%{version}.tar.bz2 %define libqofono_version 0.101 BuildRequires: cmake BuildRequires: extra-cmake-modules 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 $?) %{!?cmake_build:%define cmake_build cmake --build .} %{!?cmake_install:%define cmake_install DESTDIR="%{buildroot}" cmake --install .} Requires: libqofono-qt5 >= %{libqofono_version} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %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 %cmake . -DLIBQOFONOEXT_VERSION=$(sed 's/+.*//' <<<"%{version}") %cmake_build %install %cmake_install %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %{_libdir}/%{name}.so.* %if %{license_support} == 0 %license LICENSE.LGPL %endif %files declarative %{_libdir}/qt5/qml/org/nemomobile/ofono %files devel %{_libdir}/%{name}.so %{_libdir}/pkgconfig/qofonoext.pc %{_includedir}/qofonoext/*.h libqofonoext-1.2.0/src/000077500000000000000000000000001524406572100150205ustar00rootroot00000000000000libqofonoext-1.2.0/src/CMakeLists.txt000066400000000000000000000025621524406572100175650ustar00rootroot00000000000000add_library( qofonoext${QTVERSION_SUFFIX} SHARED qofonoext.cpp qofonoextcell.cpp qofonoextcellinfo.cpp qofonoextcellwatcher.cpp qofonoextmodemmanager.cpp qofonoextsiminfo.cpp ) set(PUBLIC_HEADER_FILES qofonoextcell.h qofonoextcellinfo.h qofonoextcellwatcher.h qofonoextmodemmanager.h qofonoextsiminfo.h qofonoext_types.h ) set_target_properties( qofonoext${QTVERSION_SUFFIX} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) target_compile_definitions(qofonoext${QTVERSION_SUFFIX} PRIVATE QOFONOEXT_LIBRARY) target_compile_options(qofonoext${QTVERSION_SUFFIX} PRIVATE -Wno-unused-parameter -Wno-psabi) target_include_directories(qofonoext${QTVERSION_SUFFIX} PRIVATE ${QOFONO_QT_INCLUDE_DIRS}) target_link_libraries(qofonoext${QTVERSION_SUFFIX} PRIVATE ${QOFONO_QT_LIBRARIES} ${QTDBUS_LIB}) ### INSTALL ### # Library install(TARGETS qofonoext${QTVERSION_SUFFIX} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # Public headers install(FILES ${PUBLIC_HEADER_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qofonoext${QTVERSION_SUFFIX} ) include(ECMGeneratePkgConfigFile) ecm_generate_pkgconfig_file( BASE_NAME qofonoext${QTVERSION_SUFFIX} INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/qofonoext${QTVERSION_SUFFIX} DESCRIPTION "Qt bindings for ofono extensions" INSTALL ) libqofonoext-1.2.0/src/qofonoext.cpp000066400000000000000000000017501524406572100175510ustar00rootroot00000000000000/**************************************************************************** ** ** 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.2.0/src/qofonoext_p.h000066400000000000000000000020511524406572100175300ustar00rootroot00000000000000/**************************************************************************** ** ** 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.2.0/src/qofonoext_types.h000066400000000000000000000020101524406572100204300ustar00rootroot00000000000000/**************************************************************************** ** ** 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.2.0/src/qofonoextcell.cpp000066400000000000000000000343331524406572100204140ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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" #include 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&, const QDBusVariant&); void RegisteredChanged(bool); 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 { const QString name; void (QOfonoExtCell::*signal)(); }; static const PropertyDesc Properties[PropertyCount]; typedef QDBusPendingReply < int, // 0. version QString, // 1. type bool, // 2. registered QVariantMap> // 3. properties GetAllReply; Private(const QString&, QOfonoExtCell*); void getAllSyncInit(); static int valueInt(Private*, Property); static Type typeFromString(const QString&); static Property propertyFromString(const QString&); static int getRssiDbm(int); static int inRange(int value, int min, int max); void updateAllAsync(); private: QOfonoExtCell* cell(); void getAllAsync(); bool pathValid(); bool updateSignalLevelDbm(); void handleGetAllReply(GetAllReply, bool); void invalidateValues(); private: // SLOTS void onGetAllFinished(QDBusPendingCallWatcher*); void onPropertyChanged(const QString&, const QDBusVariant&); void onRegisteredChanged(bool); public: bool iValid; bool iRegistered; int iProperties[PropertyCount]; int iSignalLevelDbm; QOfonoExtCell::Type iType; qint64 iNci; private: QDBusPendingCallWatcher* iPendingGetAll; QSharedPointer iCellInfo; }; const QOfonoExtCell::Private::PropertyDesc QOfonoExtCell::Private::Properties[] = { #define PropertyDesc_(x) {QStringLiteral(#x), &QOfonoExtCell::x##Changed}, 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, &QOfonoExtCellProxy::Removed, aParent, &QOfonoExtCell::removed); connect(this, &QOfonoExtCellProxy::PropertyChanged, this, &Private::onPropertyChanged); connect(this, &QOfonoExtCellProxy::RegisteredChanged, this, &Private::onRegisteredChanged); connect(iCellInfo.data(), &QOfonoExtCellInfo::cellsChanged, this, &Private::updateAllAsync); connect(iCellInfo.data(), &QOfonoExtCellInfo::validChanged, this, &Private::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; i < PropertyCount; i++) { if (Properties[i].name == aProperty) { return (Property)i; } } return PropertyUnknown; } int QOfonoExtCell::Private::valueInt( Private* aThis, Property aProperty) { return aThis ? aThis->iProperties[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, &QDBusPendingCallWatcher::finished, this, &Private::onGetAllFinished); } 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 < PropertyCount; i++) { if (iProperties[i] != prevProps[i]) { (parent->*(Properties[i].signal))(); Q_EMIT parent->propertyChanged(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 { const qint64 value = iPrivate ? iPrivate->iNci : INT64_MAX; if (value != INT64_MAX) { return QString::number(value); } return QString(); } #include "qofonoextcell.moc" libqofonoext-1.2.0/src/qofonoextcell.h000066400000000000000000000122231524406572100200530ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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* parent = Q_NULLPTR); QOfonoExtCell(QString path, bool mayBlock); // Since 1.0.27 QOfonoExtCell(QString path); ~QOfonoExtCell(); QString path() const; void setPath(QString); 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.2.0/src/qofonoextcellinfo.cpp000066400000000000000000000243741524406572100212740ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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); void CellsRemoved(QList); }; const QString QOfonoExtCellInfoProxy::INTERFACE("org.nemomobile.ofono.CellInfo"); // ========================================================================== // QOfonoExtCellInfo::Private // ========================================================================== class QOfonoExtCellInfo::Private : public QObject { Q_OBJECT public: Private(QOfonoExtCellInfo*); QString modemPath() const; void setModemPath(const QString&); void setModemPathSyncInit(const QString&); private: QOfonoExtCellInfo* parentObject() const; void getCellsSyncInit(); void getCellsAsync(); void invalidate(); void setModemPath(const QString&, QSharedPointer, void (Private::*getCells)()); void checkInterfacePresence(void (Private::*getCellsFn)()); static QStringList getPaths(const QList&); private: // SLOTS void onModemChanged(); void onGetCellsFinished(QDBusPendingCallWatcher*); void onCellsAdded(const QList&); void onCellsRemoved(const QList&); public: bool iValid; bool iFixedPath; QStringList iCells; private: QOfonoExtCellInfoProxy* iProxy; QSharedPointer iModem; }; QOfonoExtCellInfo::Private::Private( QOfonoExtCellInfo* aParent) : QObject(aParent), iValid(false), iFixedPath(false), iProxy(NULL) {} inline QOfonoExtCellInfo* QOfonoExtCellInfo::Private::parentObject() const { return qobject_cast(parent()); } inline QString QOfonoExtCellInfo::Private::modemPath() const { return iModem.isNull() ? QString() : iModem->objectPath(); } inline void QOfonoExtCellInfo::Private::setModemPath( const QString& aPath) { setModemPath(aPath, QOfonoModem::instance(aPath), &Private::getCellsAsync); } inline void QOfonoExtCellInfo::Private::setModemPathSyncInit( const QString& aPath) { setModemPath(aPath, QOfonoModem::instance(aPath, true), &Private::getCellsSyncInit); } void QOfonoExtCellInfo::Private::setModemPath( const 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(), &QOfonoModem::validChanged, this, &Private::onModemChanged); connect(iModem.data(), &QOfonoModem::interfacesChanged, this, &Private::onModemChanged); checkInterfacePresence(aGetCells); } } void QOfonoExtCellInfo::Private::getCellsAsync() { connect(new QDBusPendingCallWatcher(iProxy->GetCellsAsync(), iProxy), &QDBusPendingCallWatcher::finished, this, &Private::onGetCellsFinished); } 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, &QOfonoExtCellInfoProxy::CellsAdded, this, &Private::onCellsAdded); connect(iProxy, &QOfonoExtCellInfoProxy::CellsRemoved, this, &Private::onCellsRemoved); (this->*aGetCells)(); } else { invalidate(); } } } else { invalidate(); } } void QOfonoExtCellInfo::Private::invalidate() { if (iProxy) { delete iProxy; iProxy = NULL; } if (iValid) { iValid = false; Q_EMIT parentObject()->validChanged(); } } QStringList QOfonoExtCellInfo::Private::getPaths( const QList& aPaths) { QStringList list; const int n = aPaths.count(); list.reserve(n); 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 { QOfonoExtCellInfo* obj = parentObject(); const QStringList list(getPaths(reply.value())); if (iCells != list) { iCells = list; Q_EMIT obj->cellsChanged(); } if (!iValid) { iValid = true; Q_EMIT obj->validChanged(); } } aWatcher->deleteLater(); } void QOfonoExtCellInfo::Private::onModemChanged() { checkInterfacePresence(&Private::getCellsAsync); } void QOfonoExtCellInfo::Private::onCellsAdded( const QList& aCells) { QStringList cells; cells.reserve(aCells.count()); for (int i = 0; i < aCells.count(); i++) { const QString path(aCells.at(i).path()); if (!iCells.contains(path)) { iCells.append(path); cells.append(path); } } if (!cells.isEmpty()) { QOfonoExtCellInfo* obj = parentObject(); iCells.sort(); Q_EMIT obj->cellsAdded(cells); Q_EMIT obj->cellsChanged(); } } void QOfonoExtCellInfo::Private::onCellsRemoved( const QList& aCells) { QStringList cells; for (int i = 0; i < aCells.count(); i++) { const QString path(aCells.at(i).path()); if (iCells.removeOne(path)) { cells.append(path); } } if (!cells.isEmpty()) { QOfonoExtCellInfo* obj = parentObject(); Q_EMIT obj->cellsRemoved(cells); Q_EMIT obj->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.2.0/src/qofonoextcellinfo.h000066400000000000000000000036361524406572100207370ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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* parent = Q_NULLPTR); QOfonoExtCellInfo(QString modemPath, QObject* parent = Q_NULLPTR); // Blocks (since 1.0.27) ~QOfonoExtCellInfo(); // Shared instance(s) for C++ use static QSharedPointer instance(QString modemPath); static QSharedPointer instance(QString modemPath, bool mayBlock); // Since 1.0.27 QString modemPath() const; void setModemPath(QString); 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.2.0/src/qofonoextcellwatcher.cpp000066400000000000000000000130111524406572100217600ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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*); QOfonoExtCellWatcher* iParent; QSharedPointer iOfonoManager; QList > iCellInfoList; QList > iValidCells; QMap > iKnownCells; private: QStringList updateKnownCells(); private: // SLOTS void updateCellInfo(); void updateValidCells(); }; QOfonoExtCellWatcher::Private::Private( QOfonoExtCellWatcher* aParent) : QObject(aParent), iParent(aParent), iOfonoManager(QOfonoManager::instance()) { connect(iOfonoManager.data(), &QOfonoManager::availableChanged, this, &Private::updateValidCells); connect(iOfonoManager.data(), &QOfonoManager::modemsChanged, this, &Private::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; i < modems.count(); i++) { if (iCellInfoList.at(i)->modemPath() != modems.at(i)) { changed = true; break; } } } if (changed) { QList > bak(iCellInfoList); for (i = 0; i < iCellInfoList.count(); i++) { iCellInfoList.at(i)->disconnect(this); } iCellInfoList.clear(); for (i = 0; i < modems.count(); i++) { QSharedPointer cellInfo = QOfonoExtCellInfo::instance(modems.at(i)); iCellInfoList.append(cellInfo); connect(cellInfo.data(), &QOfonoExtCellInfo::cellsChanged, this, &Private::updateValidCells); } } } QStringList QOfonoExtCellWatcher::Private::updateKnownCells() { updateCellInfo(); QStringList allCells; int i; allCells.reserve(iCellInfoList.count()); for (i = 0; i < iCellInfoList.count(); i++) { allCells.append(iCellInfoList.at(i)->cells()); } QStringList knownCells(iKnownCells.keys()); allCells.sort(); knownCells.sort(); if (allCells != knownCells) { QMap > bak(iKnownCells); iKnownCells.clear(); for (i = 0; i < allCells.count(); i++) { QString path(allCells.at(i)); QSharedPointer 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(), &QOfonoExtCell::validChanged, this, &Private::updateValidCells); } } // Disconnect those cells that we no longer need QList > leftover = bak.values(); for (i = 0; i < leftover.count(); i++) { leftover.at(i)->disconnect(this); } } return allCells; } void QOfonoExtCellWatcher::Private::updateValidCells() { QStringList knownCells = updateKnownCells(); QStringList validCells; int i; for (i = 0; i < knownCells.count(); i++) { QString path(knownCells.at(i)); QSharedPointer cell = iKnownCells.value(path); if (cell->valid()) { validCells.append(path); } } bool changed = true; if (validCells.count() == iValidCells.count()) { changed = false; for (i = 0; i < validCells.count(); i++) { if (iValidCells.at(i)->path() != validCells.at(i)) { changed = true; break; } } } if (changed && validCells.count() == knownCells.count()) { iValidCells.clear(); for (i = 0; i < validCells.count(); i++) { iValidCells.append(iKnownCells.value(validCells.at(i))); } if (iParent) { Q_EMIT iParent->cellsChanged(); } } } 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.2.0/src/qofonoextcellwatcher.h000066400000000000000000000023751524406572100214400ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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* parent = NULL); ~QOfonoExtCellWatcher(); QList > cells() const; Q_SIGNALS: void cellsChanged(); private: class Private; Private* iPrivate; }; #endif // QOFONOEXTCELLWATCHER_H libqofonoext-1.2.0/src/qofonoextmodemmanager.cpp000066400000000000000000000611121524406572100221240ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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(const QString& aImsi) { return asyncCall("SetDefaultDataSim", aImsi); } QDBusPendingCall SetDefaultVoiceSim(const QString& aImsi) { return asyncCall("SetDefaultVoiceSim", aImsi); } QDBusPendingCall SetEnabledModems(const QList& aModems) { return asyncCall("SetEnabledModems", QVariant::fromValue(aModems)); } Q_SIGNALS: // SIGNALS void DefaultDataModemChanged(QString); void DefaultDataSimChanged(QString); void DefaultVoiceModemChanged(QString); void DefaultVoiceSimChanged(QString); void EnabledModemsChanged(QList); void MmsModemChanged(QString); void MmsSimChanged(QString); void PresentSimsChanged(int, bool); void ReadyChanged(bool); void ModemError(QDBusObjectPath, QString, QString); 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; 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*); static QStringList toStringList(const QList&); static QList toPathList(const QStringList&); QOfonoExtModemManager* parentObject() const; QStringList dummyStringList(); void getAll(); void getInterfaceVersion(); void presentSimsChanged(const QList&); void updateSimCounts(); void updateEnabledModems(const QStringList&); void updateDefaultDataModem(const QString&); void updateDefaultVoiceModem(const QString&); void updateDefaultDataSim(const QString&); void updateDefaultVoiceSim(const QString&); void updateMmsSim(const QString&); void updateMmsModem(const QString&); void updateReady(bool); private: // SLOTS void onServiceRegistered(); void onServiceUnregistered(); void onGetInterfaceVersionFinished(QDBusPendingCallWatcher*); void onGetAllFinished(QDBusPendingCallWatcher*); void onEnabledModemsChanged(const QList&); void onDefaultVoiceModemChanged(const QString&); void onDefaultDataModemChanged(const QString&); void onDefaultVoiceSimChanged(const QString&); void onDefaultDataSimChanged(const QString&); void onPresentSimsChanged(int, bool); void onMmsSimChanged(const QString&); void onMmsModemChanged(const QString&); void onReadyChanged(bool); void onModemError(const QDBusObjectPath&, const QString&, const QString&); }; /* static */ QWeakPointer QOfonoExtModemManager::Private::sSharedInstance; /* static */ QStringList QOfonoExtModemManager::Private::toStringList( const QList& aList) { QStringList stringList; const int n = aList.count(); stringList.reserve(n); for (int i = 0; i < n; i++) { stringList.append(aList.at(i).path()); } return stringList; } /* static */ QList QOfonoExtModemManager::Private::toPathList( const QStringList& aList) { QList pathList; const int n = aList.count(); pathList.reserve(n); for (int i = 0; i < n; i++) { pathList.append(QDBusObjectPath(aList.at(i))); } return pathList; } QOfonoExtModemManager::Private::Private( QOfonoExtModemManager* aParent) : QObject(aParent), iProxy(NULL), iPresentSimCount(0), iActiveSimCount(0), iInterfaceVersion(0), iReady(false), iValid(false), iErrorCount(0) { qRegisterMetaType("QOfonoExtModemManagerProxy::Error"); qDBusRegisterMetaType(); QDBusServiceWatcher* ofonoWatcher = new QDBusServiceWatcher(OFONO_SERVICE, OFONO_BUS, QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); connect(ofonoWatcher, &QDBusServiceWatcher::serviceRegistered, this, &Private::onServiceRegistered); connect(ofonoWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &Private::onServiceUnregistered); if (OFONO_BUS.interface()->isServiceRegistered(OFONO_SERVICE)) { onServiceRegistered(); } } QOfonoExtModemManager* QOfonoExtModemManager::Private::parentObject() const { return qobject_cast(parent()); } void QOfonoExtModemManager::Private::onServiceRegistered() { const bool wasValid = iValid; if (!iProxy) { iProxy = new QOfonoExtModemManagerProxy(this); if (iProxy->isValid()) { iValid = false; connect(iProxy, &QOfonoExtModemManagerProxy::EnabledModemsChanged, this, &Private::onEnabledModemsChanged); connect(iProxy, &QOfonoExtModemManagerProxy::DefaultDataModemChanged, this, &Private::onDefaultDataModemChanged); connect(iProxy, &QOfonoExtModemManagerProxy::DefaultVoiceModemChanged, this, &Private::onDefaultVoiceModemChanged); connect(iProxy, &QOfonoExtModemManagerProxy::DefaultDataSimChanged, this, &Private::onDefaultDataSimChanged); connect(iProxy, &QOfonoExtModemManagerProxy::DefaultVoiceSimChanged, this, &Private::onDefaultVoiceSimChanged); connect(iProxy, &QOfonoExtModemManagerProxy::PresentSimsChanged, this, &Private::onPresentSimsChanged); getInterfaceVersion(); } else { delete iProxy; iProxy = NULL; } } if (wasValid != iValid) { Q_EMIT parentObject()->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 parentObject()->validChanged(iValid); } } void QOfonoExtModemManager::Private::getInterfaceVersion() { iInitCall = new QDBusPendingCallWatcher(iProxy->GetInterfaceVersion(), iProxy); connect(iInitCall, &QDBusPendingCallWatcher::finished, this, &Private::onGetInterfaceVersionFinished); } 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, &QDBusPendingCallWatcher::finished, this, &Private::onGetAllFinished); } 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, &QOfonoExtModemManagerProxy::MmsSimChanged, this, &Private::onMmsSimChanged); connect(iProxy, &QOfonoExtModemManagerProxy::MmsModemChanged, this, &Private::onMmsModemChanged); } if (version >= 5 && iProxy->iInterfaceVersion < 5) { connect(iProxy, &QOfonoExtModemManagerProxy::ReadyChanged, this, &Private::onReadyChanged); } if (version >= 6 && iProxy->iInterfaceVersion < 6) { connect(iProxy, &QOfonoExtModemManagerProxy::ModemError, this, &Private::onModemError); } iProxy->iInterfaceVersion = version; } if (iInterfaceVersion != version) { iInterfaceVersion = version; Q_EMIT parentObject()->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>())); QOfonoExtModemManager* obj = parentObject(); if (iAvailableModems != list) { iAvailableModems = list; Q_EMIT obj->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 obj->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 < n; i++) { const ErrorList& errors = me.at(i); const int k = errors.count(); for (int j=0; j= 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; i < k; i++) { errorCount += errors.at(i).iCount; } } if (iErrorCount != errorCount) { iErrorCount = errorCount; Q_EMIT obj->errorCountChanged(errorCount); } if (iIMEISVs != list) { iIMEISVs = list; Q_EMIT obj->imeisvCodesChanged(iIMEISVs); } if (!iValid) { iValid = true; Q_EMIT obj->validChanged(iValid); } } aWatcher->deleteLater(); } QStringList QOfonoExtModemManager::Private::dummyStringList() { QStringList list; const int n = iAvailableModems.count(); list.reserve(n); for (int i = 0; i < n; i++) { list.append(QString()); } return list; } void QOfonoExtModemManager::Private::presentSimsChanged( const QList& aOldList) { QOfonoExtModemManager* obj = parentObject(); int i; const int n = iPresentSims.count(); QList changed; changed.reserve(n); for (i = 0; i < n; i++) { const bool prev = (ipresentSimChanged(i, iPresentSims.at(i)); } } if (aOldList != iPresentSims) { Q_EMIT obj->presentSimsChanged(iPresentSims); } } void QOfonoExtModemManager::Private::updateSimCounts() { QOfonoExtModemManager* obj = parentObject(); const int oldPresentSimCount = iPresentSimCount; const int oldActiveSimCount = iActiveSimCount; iPresentSimCount = 0; iActiveSimCount = 0; const int n = iPresentSims.count(); for (int i = 0; i < n; i++) { if (iPresentSims.at(i)) { iPresentSimCount++; if (i < iAvailableModems.count() && iEnabledModems.contains(iAvailableModems.at(i))) { iActiveSimCount++; } } } if (oldPresentSimCount != iPresentSimCount) { Q_EMIT obj->presentSimCountChanged(iPresentSimCount); } if (oldActiveSimCount != iActiveSimCount) { Q_EMIT obj->activeSimCountChanged(iActiveSimCount); } } void QOfonoExtModemManager::Private::updateEnabledModems( const QStringList& aModems) { if (iEnabledModems != aModems) { iEnabledModems = aModems; Q_EMIT parentObject()->enabledModemsChanged(aModems); } updateSimCounts(); } void QOfonoExtModemManager::Private::updateDefaultDataModem( const QString& aPath) { if (iDefaultDataModem != aPath) { iDefaultDataModem = aPath; Q_EMIT parentObject()->defaultDataModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateDefaultVoiceModem( const QString& aPath) { if (iDefaultVoiceModem != aPath) { iDefaultVoiceModem = aPath; Q_EMIT parentObject()->defaultVoiceModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateDefaultDataSim( const QString& aImsi) { if (iDefaultDataSim != aImsi) { iDefaultDataSim = aImsi; Q_EMIT parentObject()->defaultDataSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateDefaultVoiceSim( const QString& aImsi) { if (iDefaultVoiceSim != aImsi) { iDefaultVoiceSim = aImsi; Q_EMIT parentObject()->defaultVoiceSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateMmsSim( const QString& aImsi) { if (iMmsSim != aImsi) { iMmsSim = aImsi; Q_EMIT parentObject()->mmsSimChanged(aImsi); } } void QOfonoExtModemManager::Private::updateMmsModem( const QString& aPath) { if (iMmsModem != aPath) { iMmsModem = aPath; Q_EMIT parentObject()->mmsModemChanged(aPath); } } void QOfonoExtModemManager::Private::updateReady( bool aReady) { if (iReady != aReady) { iReady = aReady; Q_EMIT parentObject()->readyChanged(aReady); } } void QOfonoExtModemManager::Private::onEnabledModemsChanged( const QList& aModems) { if (!iInitCall) { updateEnabledModems(toStringList(aModems)); } } void QOfonoExtModemManager::Private::onDefaultDataModemChanged( const QString& aPath) { if (!iInitCall) { updateDefaultDataModem(aPath); } } void QOfonoExtModemManager::Private::onDefaultVoiceModemChanged( const QString& aPath) { if (!iInitCall) { updateDefaultVoiceModem(aPath); } } void QOfonoExtModemManager::Private::onDefaultDataSimChanged( const QString& aImsi) { if (!iInitCall) { updateDefaultDataSim(aImsi); } } void QOfonoExtModemManager::Private::onDefaultVoiceSimChanged( const QString& aImsi) { if (!iInitCall) { updateDefaultVoiceSim(aImsi); } } void QOfonoExtModemManager::Private::onPresentSimsChanged( int aIndex, bool aPresent) { if (!iInitCall && aIndex >= 0 && aIndex < iPresentSims.count()) { const QList oldList(iPresentSims); iPresentSims[aIndex] = aPresent; presentSimsChanged(oldList); } } void QOfonoExtModemManager::Private::onMmsSimChanged( const QString& aImsi) { if (!iInitCall) { updateMmsSim(aImsi); } } void QOfonoExtModemManager::Private::onMmsModemChanged( const QString& aPath) { if (!iInitCall) { updateMmsModem(aPath); } } void QOfonoExtModemManager::Private::onReadyChanged( bool aReady) { if (!iInitCall) { updateReady(aReady); } } void QOfonoExtModemManager::Private::onModemError( const QDBusObjectPath& aPath, const QString& aName, const QString& aMessage) { if (!iInitCall) { QOfonoExtModemManager* obj = parentObject(); iErrorCount++; Q_EMIT obj->errorCountChanged(iErrorCount); Q_EMIT obj->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); } } /* static */ QSharedPointer QOfonoExtModemManager::instance() { QSharedPointer instance = Private::sSharedInstance; if (instance.isNull()) { instance = QSharedPointer::create(); Private::sSharedInstance = instance; } return instance; } #include "qofonoextmodemmanager.moc" libqofonoext-1.2.0/src/qofonoextmodemmanager.h000066400000000000000000000104511524406572100215710ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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 = Q_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) const; Q_INVOKABLE QString imeisvAt(int) const; Q_INVOKABLE bool simPresentAt(int) const; void setEnabledModems(QStringList); void setDefaultDataSim(QString); void setDefaultVoiceSim(QString); 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.2.0/src/qofonoextsiminfo.cpp000066400000000000000000000302561524406572100211410ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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(const 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"); } QDBusPendingCall GetAll2() { return asyncCall("GetAll2"); } QDBusPendingCall SetCardLabel(const QString& aLabel) { return asyncCall("SetCardLabel", aLabel); } Q_SIGNALS: // SIGNALS void CardIdentifierChanged(QString); void ServiceProviderNameChanged(QString); void SubscriberIdentityChanged(QString); void CardLabelChanged(QString); }; const QString QOfonoExtSimInfoProxy::INTERFACE("org.nemomobile.ofono.SimInfo"); // ========================================================================== // QOfonoExtSimInfo::Private // ========================================================================== class QOfonoExtSimInfo::Private : public QObject { Q_OBJECT public: QOfonoExtSimInfoProxy* iProxy; QSharedPointer iModem; bool iValid; QString iModemPath; QString iCardIdentifier; QString iSubscriberIdentity; QString iServiceProviderName; QString iCardLabel; QScopedPointer iSetCardLabel; Private(QOfonoExtSimInfo*); QOfonoExtSimInfo* parentObject() const; QString modemPath() const; void setModemPath(const QString&); void setCardLabel(const QString&); void invalidate(); void getInterfaceVersion(); void getAll(); void getAll2(); private: // SLOTS void checkInterfacePresence(); void onGetInterfaceVersionFinished(QDBusPendingCallWatcher*); void onGetAllFinished(QDBusPendingCallWatcher*); void onGetAll2Finished(QDBusPendingCallWatcher*); void onCardIdentifierChanged(const QString&); void onSubscriberIdentityChanged(const QString&); void onServiceProviderNameChanged(const QString&); void onCardLabelChanged(const QString&); }; QOfonoExtSimInfo::Private::Private( QOfonoExtSimInfo* aParent) : QObject(aParent), iProxy(Q_NULLPTR), iValid(false) {} QOfonoExtSimInfo* QOfonoExtSimInfo::Private::parentObject() const { return qobject_cast(parent()); } QString QOfonoExtSimInfo::Private::modemPath() const { return iModem.isNull() ? QString() : iModem->objectPath(); } void QOfonoExtSimInfo::Private::setModemPath( const QString& aPath) { if (aPath != modemPath()) { if (aPath.isEmpty()) { iModem.clear(); invalidate(); } else { if (iModem) iModem->disconnect(this); iModem = QOfonoModem::instance(aPath); connect(iModem.data(), &QOfonoModem::validChanged, this, &Private::checkInterfacePresence); connect(iModem.data(), &QOfonoModem::interfacesChanged, this, &Private::checkInterfacePresence); invalidate(); checkInterfacePresence(); } Q_EMIT parentObject()->modemPathChanged(modemPath()); } } void QOfonoExtSimInfo::Private::setCardLabel( const QString& aLabel) { // It won't work if API v2 is not supported by ofono... But at least we try if (iProxy) { iProxy->SetCardLabel(aLabel); } else { iSetCardLabel.reset(new QString(aLabel)); } } 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, &QOfonoExtSimInfoProxy::CardIdentifierChanged, this, &Private::onCardIdentifierChanged); connect(iProxy, &QOfonoExtSimInfoProxy::SubscriberIdentityChanged, this, &Private::onSubscriberIdentityChanged); connect(iProxy, &QOfonoExtSimInfoProxy::ServiceProviderNameChanged, this, &Private::onServiceProviderNameChanged); connect(iProxy, &QOfonoExtSimInfoProxy::CardLabelChanged, this, &Private::onCardLabelChanged); if (iSetCardLabel) { // Hope that API v2 is supported by ofono iProxy->SetCardLabel(*iSetCardLabel); iSetCardLabel.reset(); } getInterfaceVersion(); } else { invalidate(); } } } else { invalidate(); } } void QOfonoExtSimInfo::Private::invalidate() { if (iProxy) { delete iProxy; iProxy = Q_NULLPTR; } if (iValid) { iValid = false; Q_EMIT parentObject()->validChanged(false); } } void QOfonoExtSimInfo::Private::getInterfaceVersion() { connect(new QDBusPendingCallWatcher(iProxy->GetInterfaceVersion(), iProxy), &QDBusPendingCallWatcher::finished, this, &Private::onGetInterfaceVersionFinished); } void QOfonoExtSimInfo::Private::getAll() { connect(new QDBusPendingCallWatcher(iProxy->GetAll(), iProxy), &QDBusPendingCallWatcher::finished, this, &Private::onGetAllFinished); } void QOfonoExtSimInfo::Private::getAll2() { connect(new QDBusPendingCallWatcher(iProxy->GetAll2(), iProxy), &QDBusPendingCallWatcher::finished, this, &Private::onGetAll2Finished); } void QOfonoExtSimInfo::Private::onGetInterfaceVersionFinished( QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply reply(*aWatcher); if (reply.isError()) { // Repeat the call on timeout qWarning() << reply.error(); if (QOfonoExt::isTimeout(reply.error())) { getInterfaceVersion(); } } else if (reply.value() < 2) { getAll(); } else { getAll2(); } aWatcher->deleteLater(); } 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 { QOfonoExtSimInfo* obj = parentObject(); const QString iccid(reply.argumentAt<1>()); const QString imsi(reply.argumentAt<2>()); const QString spn(reply.argumentAt<3>()); if (iCardIdentifier != iccid) { iCardIdentifier = iccid; Q_EMIT obj->cardIdentifierChanged(iccid); } if (iSubscriberIdentity != imsi) { iSubscriberIdentity = imsi; Q_EMIT obj->subscriberIdentityChanged(imsi); } if (iServiceProviderName != spn) { iServiceProviderName = spn; Q_EMIT obj->serviceProviderNameChanged(spn); } if (!iValid) { iValid = true; Q_EMIT obj->validChanged(iValid); } } aWatcher->deleteLater(); } void QOfonoExtSimInfo::Private::onGetAll2Finished( QDBusPendingCallWatcher* aWatcher) { QDBusPendingReply // CardLabel reply(*aWatcher); if (reply.isError()) { // Repeat the call on timeout qWarning() << reply.error(); if (QOfonoExt::isTimeout(reply.error())) { getAll2(); } } else { QOfonoExtSimInfo* obj = parentObject(); const QString iccid(reply.argumentAt<1>()); const QString imsi(reply.argumentAt<2>()); const QString spn(reply.argumentAt<3>()); const QString label(reply.argumentAt<4>()); if (iCardIdentifier != iccid) { iCardIdentifier = iccid; Q_EMIT obj->cardIdentifierChanged(iccid); } if (iSubscriberIdentity != imsi) { iSubscriberIdentity = imsi; Q_EMIT obj->subscriberIdentityChanged(imsi); } if (iServiceProviderName != spn) { iServiceProviderName = spn; Q_EMIT obj->serviceProviderNameChanged(spn); } if (iCardLabel != label) { iCardLabel = label; Q_EMIT obj->cardLabelChanged(label); } if (!iValid) { iValid = true; Q_EMIT obj->validChanged(iValid); } } aWatcher->deleteLater(); } void QOfonoExtSimInfo::Private::onCardIdentifierChanged( const QString& aValue) { if (iCardIdentifier != aValue) { iCardIdentifier = aValue; Q_EMIT parentObject()->cardIdentifierChanged(aValue); } } void QOfonoExtSimInfo::Private::onSubscriberIdentityChanged( const QString& aValue) { if (iSubscriberIdentity != aValue) { iSubscriberIdentity = aValue; Q_EMIT parentObject()->subscriberIdentityChanged(aValue); } } void QOfonoExtSimInfo::Private::onServiceProviderNameChanged( const QString& aValue) { if (iServiceProviderName != aValue) { iServiceProviderName = aValue; QOfonoExtSimInfo* obj = parentObject(); Q_EMIT obj->serviceProviderNameChanged(aValue); if (iCardLabel.isEmpty()) { Q_EMIT obj->cardLabelChanged(aValue); } } } void QOfonoExtSimInfo::Private::onCardLabelChanged( const QString& aValue) { if (iCardLabel != aValue) { iCardLabel = aValue; Q_EMIT parentObject()->cardLabelChanged(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(); } void QOfonoExtSimInfo::setModemPath( QString aPath) { iPrivate->setModemPath(aPath); } QString QOfonoExtSimInfo::cardIdentifier() const { return iPrivate->iCardIdentifier; } QString QOfonoExtSimInfo::subscriberIdentity() const { return iPrivate->iSubscriberIdentity; } QString QOfonoExtSimInfo::serviceProviderName() const { return iPrivate->iServiceProviderName; } // Since 1.2.0 QString QOfonoExtSimInfo::cardLabel() const { return iPrivate->iCardLabel; } void QOfonoExtSimInfo::setCardLabel( QString aLabel) { iPrivate->setCardLabel(aLabel); } #include "qofonoextsiminfo.moc" libqofonoext-1.2.0/src/qofonoextsiminfo.h000066400000000000000000000043311524406572100206010ustar00rootroot00000000000000/**************************************************************************** ** +* Copyright (C) 2026 Jolla Mobile Ltd ** 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) Q_PROPERTY(QString cardLabel READ cardLabel WRITE setCardLabel NOTIFY cardLabelChanged) // Since 1.2.0 public: explicit QOfonoExtSimInfo(QObject* parent = Q_NULLPTR); ~QOfonoExtSimInfo(); bool valid() const; QString modemPath() const; QString cardIdentifier() const; QString subscriberIdentity() const; QString serviceProviderName() const; QString cardLabel() const; // Since 1.2.0 void setModemPath(QString); void setCardLabel(QString); // Since 1.2.0 Q_SIGNALS: void validChanged(bool value); void modemPathChanged(QString value); void cardIdentifierChanged(QString value); void subscriberIdentityChanged(QString value); void serviceProviderNameChanged(QString value); void cardLabelChanged(QString value); // Since 1.2.0 private: class Private; Private* iPrivate; }; #endif // QOFONOEXTSIMINFO_H