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 }