File indexing completed on 2024-05-12 05:36:17

0001 // SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 #include "modemdetails.h"
0005 
0006 #include <KLocalizedString>
0007 
0008 #include <QDBusPendingCallWatcher>
0009 
0010 ModemDetails::ModemDetails(QObject *parent, Modem *modem)
0011     : QObject{parent}
0012     , m_modem{modem}
0013     , m_scanNetworkWatcher{nullptr}
0014     , m_isScanningNetworks{false}
0015     , m_cachedScannedNetworks{}
0016 {
0017     auto mmInterfacePointer = m_modem->m_mmInterface.data();
0018     connect(mmInterfacePointer, &ModemManager::Modem::accessTechnologiesChanged, this, [this]() -> void {
0019         Q_EMIT accessTechnologiesChanged();
0020     });
0021     connect(mmInterfacePointer, &ModemManager::Modem::deviceChanged, this, [this]() -> void {
0022         Q_EMIT deviceChanged();
0023     });
0024     connect(mmInterfacePointer, &ModemManager::Modem::deviceIdentifierChanged, this, [this]() -> void {
0025         Q_EMIT deviceIdentifierChanged();
0026     });
0027     connect(mmInterfacePointer, &ModemManager::Modem::driversChanged, this, [this]() -> void {
0028         Q_EMIT driversChanged();
0029     });
0030     connect(mmInterfacePointer, &ModemManager::Modem::equipmentIdentifierChanged, this, [this]() -> void {
0031         Q_EMIT equipmentIdentifierChanged();
0032     });
0033     connect(mmInterfacePointer, &ModemManager::Modem::manufacturerChanged, this, [this]() -> void {
0034         Q_EMIT manufacturerChanged();
0035     });
0036     connect(mmInterfacePointer, &ModemManager::Modem::modelChanged, this, [this]() -> void {
0037         Q_EMIT modelChanged();
0038     });
0039     connect(mmInterfacePointer, &ModemManager::Modem::ownNumbersChanged, this, [this]() -> void {
0040         Q_EMIT ownNumbersChanged();
0041     });
0042     connect(mmInterfacePointer, &ModemManager::Modem::pluginChanged, this, [this]() -> void {
0043         Q_EMIT pluginChanged();
0044     });
0045     connect(mmInterfacePointer, &ModemManager::Modem::powerStateChanged, this, [this]() -> void {
0046         Q_EMIT powerStateChanged();
0047     });
0048     connect(mmInterfacePointer, &ModemManager::Modem::revisionChanged, this, [this]() -> void {
0049         Q_EMIT revisionChanged();
0050     });
0051     connect(mmInterfacePointer, &ModemManager::Modem::signalQualityChanged, this, [this]() -> void {
0052         Q_EMIT signalQualityChanged();
0053     });
0054     connect(mmInterfacePointer, &ModemManager::Modem::simPathChanged, this, [this]() -> void {
0055         Q_EMIT simPathChanged();
0056     });
0057     connect(mmInterfacePointer, &ModemManager::Modem::stateChanged, this, [this]() -> void {
0058         Q_EMIT stateChanged();
0059     });
0060     connect(mmInterfacePointer, &ModemManager::Modem::stateFailedReasonChanged, this, [this]() -> void {
0061         Q_EMIT stateFailedReasonChanged();
0062     });
0063 
0064     if (m_modem->m_mm3gppDevice) {
0065         connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::operatorCodeChanged, this, [this]() -> void {
0066             Q_EMIT operatorCodeChanged();
0067         });
0068         connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::operatorNameChanged, this, [this]() -> void {
0069             Q_EMIT operatorNameChanged();
0070         });
0071         connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::registrationStateChanged, this, [this]() -> void {
0072             Q_EMIT registrationStateChanged();
0073             Q_EMIT m_modem->isRoamingChanged();
0074         });
0075     } else {
0076         qWarning() << QStringLiteral("3gpp device not found!");
0077     }
0078 
0079     // m_modem->m_nmModem may be nullptr, listen for updates
0080     connect(m_modem, &Modem::nmModemChanged, this, &ModemDetails::updateNMSignals);
0081     updateNMSignals();
0082 }
0083 
0084 void ModemDetails::updateNMSignals()
0085 {
0086     if (m_modem->m_nmModem) {
0087         connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::firmwareVersionChanged, this, [this]() -> void {
0088             Q_EMIT firmwareVersionChanged();
0089         });
0090         connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::interfaceNameChanged, this, [this]() -> void {
0091             Q_EMIT interfaceNameChanged();
0092         });
0093         connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::meteredChanged, this, [this]() -> void {
0094             Q_EMIT meteredChanged();
0095         });
0096     }
0097 }
0098 
0099 ModemDetails &ModemDetails::operator=(ModemDetails &&other)
0100 {
0101     swap(other);
0102     return *this;
0103 }
0104 
0105 void ModemDetails::swap(ModemDetails &other)
0106 {
0107     std::swap(m_modem, other.m_modem);
0108     std::swap(m_cachedScannedNetworks, other.m_cachedScannedNetworks);
0109     std::swap(m_isScanningNetworks, other.m_isScanningNetworks);
0110     std::swap(m_scanNetworkWatcher, other.m_scanNetworkWatcher);
0111 }
0112 
0113 QStringList ModemDetails::accessTechnologies()
0114 {
0115     QStringList list;
0116     auto flags = m_modem->m_mmInterface->accessTechnologies();
0117     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) {
0118         list.push_back(i18n("Unknown"));
0119     }
0120     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_POTS) {
0121         list.push_back(i18n("POTS"));
0122     }
0123     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GSM) {
0124         list.push_back(i18n("GSM"));
0125     }
0126     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT) {
0127         list.push_back(i18n("GSM Compact"));
0128     }
0129     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GPRS) {
0130         list.push_back(i18n("GPRS"));
0131     }
0132     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EDGE) {
0133         list.push_back(i18n("EDGE"));
0134     }
0135     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_UMTS) {
0136         list.push_back(i18n("UMTS"));
0137     }
0138     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSDPA) {
0139         list.push_back(i18n("HSDPA"));
0140     }
0141     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSUPA) {
0142         list.push_back(i18n("HSUPA"));
0143     }
0144     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSPA) {
0145         list.push_back(i18n("HSPA"));
0146     }
0147     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS) {
0148         list.push_back(i18n("HSPA+"));
0149     }
0150     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) {
0151         list.push_back(i18n("CDMA2000 1xRTT"));
0152     }
0153     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDO0) {
0154         list.push_back(i18n("CDMA2000 EVDO-0"));
0155     }
0156     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDOA) {
0157         list.push_back(i18n("CDMA2000 EVDO-A"));
0158     }
0159     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDOB) {
0160         list.push_back(i18n("CDMA2000 EVDO-B"));
0161     }
0162     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_LTE) {
0163         list.push_back(i18n("LTE"));
0164     }
0165     if (flags & MM_MODEM_ACCESS_TECHNOLOGY_5GNR) {
0166         list.push_back(i18n("5GNR"));
0167     }
0168     return list;
0169 }
0170 
0171 QString ModemDetails::device()
0172 {
0173     return m_modem->m_mmInterface->device();
0174 }
0175 
0176 QString ModemDetails::deviceIdentifier()
0177 {
0178     return m_modem->m_mmInterface->deviceIdentifier();
0179 }
0180 
0181 QStringList ModemDetails::drivers()
0182 {
0183     return m_modem->m_mmInterface->drivers();
0184 }
0185 
0186 QString ModemDetails::equipmentIdentifier()
0187 {
0188     return m_modem->m_mmInterface->equipmentIdentifier();
0189 }
0190 
0191 bool ModemDetails::isEnabled()
0192 {
0193     return m_modem->m_mmInterface->isEnabled();
0194 }
0195 
0196 QString ModemDetails::manufacturer()
0197 {
0198     return m_modem->m_mmInterface->manufacturer();
0199 }
0200 
0201 QString ModemDetails::model()
0202 {
0203     return m_modem->m_mmInterface->model();
0204 }
0205 
0206 QStringList ModemDetails::ownNumbers()
0207 {
0208     return m_modem->m_mmInterface->ownNumbers();
0209 }
0210 
0211 QString ModemDetails::plugin()
0212 {
0213     return m_modem->m_mmInterface->plugin();
0214 }
0215 
0216 QString ModemDetails::powerState()
0217 {
0218     switch (m_modem->m_mmInterface->powerState()) {
0219     case MM_MODEM_POWER_STATE_UNKNOWN:
0220         return i18n("Unknown");
0221     case MM_MODEM_POWER_STATE_OFF:
0222         return i18n("Off");
0223     case MM_MODEM_POWER_STATE_LOW:
0224         return i18n("Low-power mode");
0225     case MM_MODEM_POWER_STATE_ON:
0226         return i18n("Full power mode");
0227     }
0228     return {};
0229 }
0230 
0231 QString ModemDetails::revision()
0232 {
0233     return m_modem->m_mmInterface->revision();
0234 }
0235 
0236 uint ModemDetails::signalQuality()
0237 {
0238     return m_modem->m_mmInterface->signalQuality().signal;
0239 }
0240 
0241 QString ModemDetails::simPath()
0242 {
0243     return m_modem->m_mmInterface->simPath();
0244 }
0245 
0246 QString ModemDetails::state()
0247 {
0248     switch (m_modem->m_mmInterface->state()) {
0249     case MM_MODEM_STATE_FAILED:
0250         return i18n("Failed");
0251     case MM_MODEM_STATE_UNKNOWN:
0252         return i18n("Unknown");
0253     case MM_MODEM_STATE_INITIALIZING:
0254         return i18n("Initializing");
0255     case MM_MODEM_STATE_LOCKED:
0256         return i18n("Locked");
0257     case MM_MODEM_STATE_DISABLED:
0258         return i18n("Disabled");
0259     case MM_MODEM_STATE_DISABLING:
0260         return i18n("Disabling");
0261     case MM_MODEM_STATE_ENABLING:
0262         return i18n("Enabling");
0263     case MM_MODEM_STATE_ENABLED:
0264         return i18n("Enabled");
0265     case MM_MODEM_STATE_SEARCHING:
0266         return i18n("Searching for network provider");
0267     case MM_MODEM_STATE_REGISTERED:
0268         return i18n("Registered with network provider");
0269     case MM_MODEM_STATE_DISCONNECTING:
0270         return i18n("Disconnecting");
0271     case MM_MODEM_STATE_CONNECTING:
0272         return i18n("Connecting");
0273     case MM_MODEM_STATE_CONNECTED:
0274         return i18n("Connected");
0275     }
0276     return {};
0277 }
0278 
0279 QString ModemDetails::stateFailedReason()
0280 {
0281     switch (m_modem->m_mmInterface->stateFailedReason()) {
0282     case MM_MODEM_STATE_FAILED_REASON_NONE:
0283         return i18n("No error.");
0284     case MM_MODEM_STATE_FAILED_REASON_UNKNOWN:
0285         return i18n("Unknown error.");
0286     case MM_MODEM_STATE_FAILED_REASON_SIM_MISSING:
0287         return i18n("SIM is required but missing.");
0288     case MM_MODEM_STATE_FAILED_REASON_SIM_ERROR:
0289         return i18n("SIM is available but unusable.");
0290     }
0291     return {};
0292 }
0293 
0294 QString ModemDetails::operatorCode()
0295 {
0296     return m_modem->m_mm3gppDevice ? m_modem->m_mm3gppDevice->operatorCode() : QString{};
0297 }
0298 
0299 QString ModemDetails::operatorName()
0300 {
0301     return m_modem->m_mm3gppDevice ? m_modem->m_mm3gppDevice->operatorName() : QString{};
0302 }
0303 
0304 QString ModemDetails::registrationState()
0305 {
0306     if (!m_modem->m_mm3gppDevice) {
0307         return QString{};
0308     }
0309 
0310     switch (m_modem->m_mm3gppDevice->registrationState()) {
0311     case MM_MODEM_3GPP_REGISTRATION_STATE_IDLE:
0312         return i18n("Not registered, not searching for new operator to register.");
0313     case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
0314         return i18n("Registered on home network.");
0315     case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING:
0316         return i18n("Not registered, searching for new operator to register with.");
0317     case MM_MODEM_3GPP_REGISTRATION_STATE_DENIED:
0318         return i18n("Registration denied.");
0319     case MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN:
0320         return i18n("Unknown registration status.");
0321     case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
0322         return i18n("Registered on a roaming network.");
0323     case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY:
0324         return i18n("Registered for \"SMS only\", on home network.");
0325     case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY:
0326         return i18n("Registered for \"SMS only\", roaming network.");
0327     case MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY:
0328         return i18n("Emergency services only.");
0329     case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED:
0330         return i18n("Registered for \"CSFB not preferred\", home network.");
0331     case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED:
0332         return i18n("Registered for \"CSFB not preferred\", roaming network.");
0333     case MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS:
0334         return i18n("Attached for access to Restricted Local Operator Services.");
0335     }
0336     return {};
0337 }
0338 
0339 Q_DECLARE_METATYPE(MMModem3gppNetworkAvailability)
0340 Q_DECLARE_METATYPE(MMModemAccessTechnology)
0341 
0342 QList<AvailableNetwork *> ModemDetails::networks()
0343 {
0344     return m_cachedScannedNetworks;
0345 }
0346 
0347 Q_INVOKABLE void ModemDetails::scanNetworks()
0348 {
0349     for (auto p : m_cachedScannedNetworks) {
0350         p->deleteLater();
0351     }
0352     m_cachedScannedNetworks.clear();
0353 
0354     if (m_modem->m_mm3gppDevice) {
0355         qDebug() << QStringLiteral("Scanning for available networks...");
0356 
0357         QDBusPendingReply<ModemManager::QVariantMapList> reply = m_modem->m_mm3gppDevice->scan();
0358 
0359         m_isScanningNetworks = true;
0360         Q_EMIT isScanningNetworksChanged();
0361         m_scanNetworkWatcher = new QDBusPendingCallWatcher(reply, this);
0362         connect(m_scanNetworkWatcher, &QDBusPendingCallWatcher::finished, this, &ModemDetails::scanNetworksFinished);
0363     }
0364 
0365     Q_EMIT networksChanged();
0366 }
0367 
0368 void ModemDetails::scanNetworksFinished(QDBusPendingCallWatcher *call)
0369 {
0370     QDBusPendingReply<ModemManager::QVariantMapList> reply = *call;
0371     if (reply.isError()) {
0372         qDebug() << QStringLiteral("Scanning failed:") << reply.error().message();
0373         CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Scanning networks failed: %1", reply.error().message()));
0374     } else {
0375         ModemManager::QVariantMapList list = reply.value();
0376 
0377         for (auto &var : list) {
0378             auto status = var[QStringLiteral("status")].value<MMModem3gppNetworkAvailability>();
0379 
0380             if (status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT || status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE) {
0381                 auto network = new AvailableNetwork{this,
0382                                                     m_modem->m_mm3gppDevice,
0383                                                     status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT,
0384                                                     var[QStringLiteral("operator-long")].toString(),
0385                                                     var[QStringLiteral("operator-short")].toString(),
0386                                                     var[QStringLiteral("operator-code")].toString(),
0387                                                     var[QStringLiteral("access-technology")].value<MMModemAccessTechnology>()};
0388                 m_cachedScannedNetworks.push_back(network);
0389             }
0390         }
0391     }
0392     m_isScanningNetworks = false;
0393     Q_EMIT networksChanged();
0394     Q_EMIT isScanningNetworksChanged();
0395 
0396     call->deleteLater();
0397 }
0398 
0399 bool ModemDetails::isScanningNetworks()
0400 {
0401     return m_isScanningNetworks;
0402 }
0403 
0404 QString ModemDetails::firmwareVersion()
0405 {
0406     if (!m_modem->m_nmModem) {
0407         return QString{};
0408     }
0409     return m_modem->m_nmModem->firmwareVersion();
0410 }
0411 
0412 QString ModemDetails::interfaceName()
0413 {
0414     if (!m_modem->m_nmModem) {
0415         return QString{};
0416     }
0417     return m_modem->m_nmModem->interfaceName();
0418 }
0419 
0420 QString ModemDetails::metered()
0421 {
0422     if (!m_modem->m_nmModem) {
0423         return QString{};
0424     }
0425 
0426     switch (m_modem->m_nmModem->metered()) {
0427     case NetworkManager::Device::MeteredStatus::UnknownStatus:
0428         return i18n("Unknown");
0429     case NetworkManager::Device::MeteredStatus::Yes:
0430         return i18n("Yes");
0431     case NetworkManager::Device::MeteredStatus::No:
0432         return i18n("No");
0433     case NetworkManager::Device::MeteredStatus::GuessYes:
0434         return i18n("GuessYes");
0435     case NetworkManager::Device::MeteredStatus::GuessNo:
0436         return i18n("GuessNo");
0437     }
0438     return QString{};
0439 }
0440 
0441 AvailableNetwork::AvailableNetwork(QObject *parent,
0442                                    ModemManager::Modem3gpp::Ptr mm3gppDevice,
0443                                    bool isCurrentlyUsed,
0444                                    QString operatorLong,
0445                                    QString operatorShort,
0446                                    QString operatorCode,
0447                                    MMModemAccessTechnology accessTechnology)
0448     : QObject{parent}
0449     , m_isCurrentlyUsed{isCurrentlyUsed}
0450     , m_operatorLong{operatorLong}
0451     , m_operatorShort{operatorShort}
0452     , m_operatorCode{operatorCode}
0453     , m_accessTechnology{}
0454     , m_mm3gppDevice{mm3gppDevice}
0455 {
0456     switch (accessTechnology) {
0457     case MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN:
0458         m_accessTechnology = i18n("Unknown");
0459         break;
0460     case MM_MODEM_ACCESS_TECHNOLOGY_POTS:
0461         m_accessTechnology = i18n("POTS");
0462         break;
0463     case MM_MODEM_ACCESS_TECHNOLOGY_GSM:
0464         m_accessTechnology = i18n("2G");
0465         break;
0466     case MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT:
0467         m_accessTechnology = i18n("2G");
0468         break;
0469     case MM_MODEM_ACCESS_TECHNOLOGY_GPRS:
0470         m_accessTechnology = i18n("2G");
0471         break;
0472     case MM_MODEM_ACCESS_TECHNOLOGY_EDGE:
0473         m_accessTechnology = i18n("2G");
0474         break;
0475     case MM_MODEM_ACCESS_TECHNOLOGY_UMTS:
0476         m_accessTechnology = i18n("3G");
0477         break;
0478     case MM_MODEM_ACCESS_TECHNOLOGY_HSDPA:
0479         m_accessTechnology = i18n("3G");
0480         break;
0481     case MM_MODEM_ACCESS_TECHNOLOGY_HSUPA:
0482         m_accessTechnology = i18n("3G");
0483         break;
0484     case MM_MODEM_ACCESS_TECHNOLOGY_HSPA:
0485         m_accessTechnology = i18n("3G");
0486         break;
0487     case MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS:
0488         m_accessTechnology = i18n("3G");
0489         break;
0490     case MM_MODEM_ACCESS_TECHNOLOGY_1XRTT:
0491         m_accessTechnology = i18n("3G");
0492         break;
0493     case MM_MODEM_ACCESS_TECHNOLOGY_EVDO0:
0494         m_accessTechnology = i18n("3G");
0495         break;
0496     case MM_MODEM_ACCESS_TECHNOLOGY_EVDOA:
0497         m_accessTechnology = i18n("3G");
0498         break;
0499     case MM_MODEM_ACCESS_TECHNOLOGY_EVDOB:
0500         m_accessTechnology = i18n("3G");
0501         break;
0502     case MM_MODEM_ACCESS_TECHNOLOGY_LTE:
0503         m_accessTechnology = i18n("4G");
0504         break;
0505     case MM_MODEM_ACCESS_TECHNOLOGY_5GNR:
0506         m_accessTechnology = i18n("5G");
0507         break;
0508     case MM_MODEM_ACCESS_TECHNOLOGY_ANY:
0509         m_accessTechnology = i18n("Any");
0510         break;
0511     }
0512 }
0513 
0514 bool AvailableNetwork::isCurrentlyUsed()
0515 {
0516     return m_isCurrentlyUsed;
0517 }
0518 
0519 QString AvailableNetwork::operatorLong()
0520 {
0521     return m_operatorLong;
0522 }
0523 
0524 QString AvailableNetwork::operatorShort()
0525 {
0526     return m_operatorShort;
0527 }
0528 
0529 QString AvailableNetwork::operatorCode()
0530 {
0531     return m_operatorCode;
0532 }
0533 
0534 QString AvailableNetwork::accessTechnology()
0535 {
0536     return m_accessTechnology;
0537 }
0538 
0539 void AvailableNetwork::registerToNetwork()
0540 {
0541     if (!m_isCurrentlyUsed && m_mm3gppDevice) {
0542         m_mm3gppDevice->registerToNetwork(m_operatorCode);
0543     }
0544 }