File indexing completed on 2024-04-21 03:59:49

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