File indexing completed on 2024-04-28 15:32:56

0001 /*
0002     SPDX-FileCopyrightText: 2008, 2011 Will Stephenson <wstephenson@kde.org>
0003     SPDX-FileCopyrightText: 2010 Lamarque Souza <lamarque@kde.org>
0004     SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com>
0005     SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com>
0006     SPDX-FileCopyrightText: 2013-2015 Jan Grulich <jgrulich@redhat.com>
0007 
0008     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0009 */
0010 
0011 #include "manager.h"
0012 #include "manager_p.h"
0013 
0014 #ifdef MMQT_STATIC
0015 #include "dbus/fakedbus.h"
0016 #else
0017 #include "dbus/dbus.h"
0018 #endif
0019 #include "generictypes.h"
0020 #include "generictypes_p.h"
0021 #include "macros_p.h"
0022 #include "mmdebug_p.h"
0023 #include "modem.h"
0024 
0025 Q_GLOBAL_STATIC(ModemManager::ModemManagerPrivate, globalModemManager)
0026 
0027 ModemManager::ModemManagerPrivate::ModemManagerPrivate()
0028 #ifdef MMQT_STATIC
0029     : watcher(QLatin1String(MMQT_DBUS_SERVICE),
0030               QDBusConnection::sessionBus(),
0031               QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
0032               this)
0033     , iface(QLatin1String(MMQT_DBUS_SERVICE), QLatin1String(MMQT_DBUS_PATH), QDBusConnection::sessionBus(), this)
0034     , manager(QLatin1String(MMQT_DBUS_SERVICE), QLatin1String(MMQT_DBUS_PATH), QDBusConnection::sessionBus(), this)
0035 #else
0036     : watcher(QLatin1String(MMQT_DBUS_SERVICE),
0037               QDBusConnection::systemBus(),
0038               QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
0039               this)
0040     , iface(QLatin1String(MMQT_DBUS_SERVICE), QLatin1String(MMQT_DBUS_PATH), QDBusConnection::systemBus(), this)
0041     , manager(QLatin1String(MMQT_DBUS_SERVICE), QLatin1String(MMQT_DBUS_PATH), QDBusConnection::systemBus(), this)
0042 #endif
0043 {
0044     qDBusRegisterMetaType<QList<QDBusObjectPath>>();
0045     registerModemManagerTypes();
0046 
0047     bool serviceFound = manager.isValid();
0048     if (!serviceFound) {
0049         // find out whether it will be activated automatically
0050         QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"),
0051                                                               QStringLiteral("/org/freedesktop/DBus"),
0052                                                               QStringLiteral("org.freedesktop.DBus"),
0053                                                               QStringLiteral("ListActivatableNames"));
0054 #ifdef MMQT_STATIC
0055         QDBusReply<QStringList> reply = QDBusConnection::sessionBus().call(message);
0056         if (reply.isValid() && reply.value().contains(QLatin1String(MMQT_DBUS_SERVICE))) {
0057             QDBusConnection::sessionBus().interface()->startService(QLatin1String(MMQT_DBUS_SERVICE));
0058             serviceFound = true;
0059         }
0060     }
0061 #else
0062         QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(message);
0063         if (reply.isValid() && reply.value().contains(QLatin1String(MMQT_DBUS_SERVICE))) {
0064             QDBusConnection::systemBus().interface()->startService(QLatin1String(MMQT_DBUS_SERVICE));
0065             serviceFound = true;
0066         }
0067     }
0068 #endif
0069 
0070     if (serviceFound) {
0071         connect(&manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, this, &ModemManagerPrivate::onInterfacesAdded);
0072         connect(&manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, this, &ModemManagerPrivate::onInterfacesRemoved);
0073     }
0074 
0075     connect(&watcher, &QDBusServiceWatcher::serviceRegistered, this, &ModemManagerPrivate::daemonRegistered);
0076     connect(&watcher, &QDBusServiceWatcher::serviceUnregistered, this, &ModemManagerPrivate::daemonUnregistered);
0077 
0078     init();
0079 }
0080 
0081 ModemManager::ModemManagerPrivate::~ModemManagerPrivate()
0082 {
0083 }
0084 
0085 void ModemManager::ModemManagerPrivate::init()
0086 {
0087     modemList.clear();
0088 
0089     QDBusPendingReply<DBUSManagerStruct> reply = manager.GetManagedObjects();
0090     reply.waitForFinished();
0091     if (!reply.isError()) { // enum devices
0092         Q_FOREACH (const QDBusObjectPath &path, reply.value().keys()) {
0093             const QString uni = path.path();
0094             qCDebug(MMQT) << "Adding device" << uni;
0095 
0096             if (uni == QLatin1String(MMQT_DBUS_PATH) || !uni.startsWith(QLatin1String(MMQT_DBUS_MODEM_PREFIX))) {
0097                 continue;
0098             }
0099 
0100             modemList.insert(uni, ModemDevice::Ptr());
0101             Q_EMIT modemAdded(uni);
0102         }
0103     } else { // show error
0104         qCWarning(MMQT) << "Failed enumerating MM objects:" << reply.error().name() << "\n" << reply.error().message();
0105     }
0106 }
0107 
0108 ModemManager::ModemDevice::Ptr ModemManager::ModemManagerPrivate::findModemDevice(const QString &uni)
0109 {
0110     ModemDevice::Ptr modem;
0111     if (modemList.contains(uni)) {
0112         if (modemList.value(uni)) {
0113             modem = modemList.value(uni);
0114         } else {
0115             modem = ModemDevice::Ptr(new ModemDevice(uni), &QObject::deleteLater);
0116             modemList[uni] = modem;
0117         }
0118     }
0119     return modem;
0120 }
0121 
0122 ModemManager::ModemDevice::List ModemManager::ModemManagerPrivate::modemDevices()
0123 {
0124     ModemDevice::List list;
0125 
0126     QMap<QString, ModemDevice::Ptr>::const_iterator i;
0127     for (i = modemList.constBegin(); i != modemList.constEnd(); ++i) {
0128         ModemDevice::Ptr modem = findModemDevice(i.key());
0129         if (!modem.isNull()) {
0130             list.append(modem);
0131         } else {
0132             qCWarning(MMQT) << "warning: null modem Interface for" << i.key();
0133         }
0134     }
0135 
0136     return list;
0137 }
0138 
0139 void ModemManager::ModemManagerPrivate::scanDevices()
0140 {
0141     iface.ScanDevices();
0142 }
0143 
0144 void ModemManager::ModemManagerPrivate::daemonRegistered()
0145 {
0146     init();
0147     Q_EMIT serviceAppeared();
0148 }
0149 
0150 void ModemManager::ModemManagerPrivate::daemonUnregistered()
0151 {
0152     Q_EMIT serviceDisappeared();
0153     modemList.clear();
0154 }
0155 
0156 void ModemManager::ModemManagerPrivate::onInterfacesAdded(const QDBusObjectPath &object_path, const MMVariantMapMap &interfaces_and_properties)
0157 {
0158     // TODO control added bearers and sim cards
0159 
0160     const QString uni = object_path.path();
0161 
0162     /* Ignore non-modems */
0163     if (!uni.startsWith(QLatin1String(MMQT_DBUS_MODEM_PREFIX))) {
0164         return;
0165     }
0166 
0167     qCDebug(MMQT) << uni << "has new interfaces:" << interfaces_and_properties.keys();
0168 
0169     // new device, we don't know it yet
0170     if (!modemList.contains(uni)) {
0171         modemList.insert(uni, ModemDevice::Ptr());
0172         Q_EMIT modemAdded(uni);
0173     }
0174     // re-Q_EMIT in case of modem type change (GSM <-> CDMA)
0175     else if (modemList.contains(uni)
0176              && (interfaces_and_properties.keys().contains(QLatin1String(MMQT_DBUS_INTERFACE_MODEM_MODEM3GPP))
0177                  || interfaces_and_properties.keys().contains(QLatin1String(MMQT_DBUS_INTERFACE_MODEM_MODEMCDMA)))) {
0178         Q_EMIT modemAdded(uni);
0179     }
0180 }
0181 
0182 void ModemManager::ModemManagerPrivate::onInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
0183 {
0184     // TODO control removed bearers and sim cards
0185 
0186     const QString uni = object_path.path();
0187 
0188     /* Ignore non-modems */
0189     if (!uni.startsWith(QLatin1String(MMQT_DBUS_MODEM_PREFIX))) {
0190         return;
0191     }
0192 
0193     qCDebug(MMQT) << uni << "lost interfaces:" << interfaces;
0194 
0195     ModemDevice::Ptr modem = findModemDevice(uni);
0196 
0197     // Remove modem when there is no interface or Modem interfaces has been removed
0198     if (!uni.isEmpty() && (interfaces.isEmpty() || (modem && modem->interfaces().isEmpty()) || interfaces.contains(QLatin1String(MMQT_DBUS_INTERFACE_MODEM)))) {
0199         Q_EMIT modemRemoved(uni);
0200         modemList.remove(uni);
0201     }
0202 }
0203 
0204 ModemManager::ModemDevice::Ptr ModemManager::findModemDevice(const QString &uni)
0205 {
0206     return globalModemManager->findModemDevice(uni);
0207 }
0208 
0209 ModemManager::ModemDevice::List ModemManager::modemDevices()
0210 {
0211     return globalModemManager->modemDevices();
0212 }
0213 
0214 ModemManager::Notifier *ModemManager::notifier()
0215 {
0216     return globalModemManager;
0217 }
0218 
0219 void ModemManager::scanDevices()
0220 {
0221     globalModemManager->scanDevices();
0222 }
0223 
0224 #include "moc_manager.cpp"
0225 #include "moc_manager_p.cpp"