File indexing completed on 2024-04-14 05:19:45

0001 /*
0002  *  SPDX-FileCopyrightText: 2010-2012 Alejandro Fiestas Olivares <afiestas@kde.org>
0003  *  SPDX-FileCopyrightText: 2010 Eduardo Robles Elvira <edulix@gmail.com>
0004  *  SPDX-FileCopyrightText: 2010 UFO Coders <info@ufocoders.com>
0005  *  SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
0006  *
0007  *  SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #include "bluedevildaemon.h"
0011 #include "bluedevil_kded.h"
0012 #include "bluezagent.h"
0013 #include "devicemonitor.h"
0014 #include "obexagent.h"
0015 #include "obexftp.h"
0016 #include "version.h"
0017 
0018 #include <QDBusMetaType>
0019 #include <QTimer>
0020 
0021 #include <KAboutData>
0022 #include <KLocalizedString>
0023 #include <KPluginFactory>
0024 
0025 #include <BluezQt/Adapter>
0026 #include <BluezQt/Device>
0027 #include <BluezQt/InitManagerJob>
0028 #include <BluezQt/InitObexManagerJob>
0029 #include <BluezQt/PendingCall>
0030 
0031 K_PLUGIN_FACTORY_WITH_JSON(BlueDevilFactory, "bluedevil.json", registerPlugin<BlueDevilDaemon>();)
0032 
0033 typedef QMap<QString, QString> DeviceInfo;
0034 typedef QMap<QString, DeviceInfo> QMapDeviceInfo;
0035 
0036 Q_DECLARE_METATYPE(DeviceInfo)
0037 Q_DECLARE_METATYPE(QMapDeviceInfo)
0038 
0039 struct BlueDevilDaemon::Private {
0040     BluezQt::Manager *m_manager = nullptr;
0041     BluezQt::ObexManager *m_obexManager = nullptr;
0042 
0043     QTimer m_timer;
0044     ObexFtp *m_obexFtp = nullptr;
0045     ObexAgent *m_obexAgent = nullptr;
0046     BluezAgent *m_bluezAgent = nullptr;
0047     DeviceMonitor *m_deviceMonitor = nullptr;
0048 };
0049 
0050 BlueDevilDaemon::BlueDevilDaemon(QObject *parent, const QList<QVariant> &)
0051     : KDEDModule(parent)
0052     , d(new Private)
0053 {
0054     qDBusRegisterMetaType<DeviceInfo>();
0055     qDBusRegisterMetaType<QMapDeviceInfo>();
0056 
0057     d->m_manager = new BluezQt::Manager(this);
0058     d->m_obexManager = new BluezQt::ObexManager(this);
0059     d->m_obexFtp = new ObexFtp(this);
0060     d->m_obexAgent = new ObexAgent(this);
0061     d->m_bluezAgent = new BluezAgent(this);
0062     d->m_deviceMonitor = new DeviceMonitor(this);
0063 
0064     d->m_timer.setSingleShot(true);
0065     connect(&d->m_timer, &QTimer::timeout, this, &BlueDevilDaemon::stopDiscovering);
0066 
0067     KAboutData aboutData(QStringLiteral("bluedevildaemon"),
0068                          i18n("Bluetooth Daemon"),
0069                          QStringLiteral(BLUEDEVIL_VERSION_STRING),
0070                          i18n("Bluetooth Daemon"),
0071                          KAboutLicense::GPL,
0072                          i18n("(c) 2010, UFO Coders"));
0073 
0074     aboutData.addAuthor(QStringLiteral("David Rosca"), //
0075                         i18n("Maintainer"),
0076                         QStringLiteral("nowrep@gmail.com"),
0077                         QStringLiteral("http://david.rosca.cz"));
0078 
0079     aboutData.addAuthor(QStringLiteral("Alejandro Fiestas Olivares"),
0080                         i18n("Previous Maintainer"),
0081                         QStringLiteral("afiestas@kde.org"),
0082                         QStringLiteral("http://www.afiestas.org"));
0083 
0084     aboutData.addAuthor(QStringLiteral("Eduardo Robles Elvira"),
0085                         i18n("Previous Maintainer"),
0086                         QStringLiteral("edulix@gmail.com"),
0087                         QStringLiteral("http://blog.edulix.es"));
0088 
0089     aboutData.setComponentName(QStringLiteral("bluedevil"));
0090 
0091     // Initialize BluezQt
0092     BluezQt::InitManagerJob *job = d->m_manager->init();
0093     job->start();
0094     connect(job, &BluezQt::InitManagerJob::result, this, &BlueDevilDaemon::initJobResult);
0095 
0096     BluezQt::InitObexManagerJob *initJob = d->m_obexManager->init();
0097     initJob->start();
0098     connect(initJob, &BluezQt::InitObexManagerJob::result, this, &BlueDevilDaemon::initObexJobResult);
0099 
0100     qCDebug(BLUEDEVIL_KDED_LOG) << "Created";
0101 }
0102 
0103 BlueDevilDaemon::~BlueDevilDaemon()
0104 {
0105     d->m_manager->unregisterAgent(d->m_bluezAgent);
0106     d->m_obexManager->unregisterAgent(d->m_obexAgent);
0107     d->m_deviceMonitor->saveState();
0108 
0109     qCDebug(BLUEDEVIL_KDED_LOG) << "Destroyed";
0110 
0111     delete d;
0112 }
0113 
0114 bool BlueDevilDaemon::isOnline()
0115 {
0116     return d->m_manager->isBluetoothOperational();
0117 }
0118 
0119 QMapDeviceInfo BlueDevilDaemon::allDevices()
0120 {
0121     QMapDeviceInfo devices;
0122 
0123     Q_FOREACH (BluezQt::DevicePtr device, d->m_manager->devices()) {
0124         devices[device->address()] = deviceToInfo(device);
0125     }
0126 
0127     return devices;
0128 }
0129 
0130 DeviceInfo BlueDevilDaemon::device(const QString &address)
0131 {
0132     BluezQt::DevicePtr device = d->m_manager->deviceForAddress(address);
0133     return deviceToInfo(device);
0134 }
0135 
0136 void BlueDevilDaemon::startDiscovering(quint32 timeout)
0137 {
0138     if (!d->m_manager->usableAdapter()) {
0139         return;
0140     }
0141 
0142     qCDebug(BLUEDEVIL_KDED_LOG) << "Start discovering for" << timeout << "ms";
0143 
0144     d->m_manager->usableAdapter()->startDiscovery();
0145 
0146     if (timeout > 0) {
0147         d->m_timer.start(timeout);
0148     }
0149 }
0150 
0151 void BlueDevilDaemon::stopDiscovering()
0152 {
0153     if (!d->m_manager->usableAdapter()) {
0154         return;
0155     }
0156 
0157     qCDebug(BLUEDEVIL_KDED_LOG) << "Stop discovering";
0158 
0159     if (d->m_manager->usableAdapter()->isDiscovering()) {
0160         d->m_manager->usableAdapter()->stopDiscovery();
0161     }
0162 }
0163 
0164 BluezQt::Manager *BlueDevilDaemon::manager() const
0165 {
0166     return d->m_manager;
0167 }
0168 
0169 BluezQt::ObexManager *BlueDevilDaemon::obexManager() const
0170 {
0171     return d->m_obexManager;
0172 }
0173 
0174 void BlueDevilDaemon::initJobResult(BluezQt::InitManagerJob *job)
0175 {
0176     if (job->error()) {
0177         qCDebug(BLUEDEVIL_KDED_LOG) << "Error initializing manager:" << job->errorText();
0178         return;
0179     }
0180 
0181     operationalChanged(d->m_manager->isOperational());
0182     connect(d->m_manager, &BluezQt::Manager::operationalChanged, this, &BlueDevilDaemon::operationalChanged);
0183 }
0184 
0185 void BlueDevilDaemon::initObexJobResult(BluezQt::InitObexManagerJob *job)
0186 {
0187     if (job->error()) {
0188         qCDebug(BLUEDEVIL_KDED_LOG) << "Error initializing obex manager:" << job->errorText();
0189         return;
0190     }
0191 
0192     obexOperationalChanged(d->m_obexManager->isOperational());
0193     connect(d->m_obexManager, &BluezQt::ObexManager::operationalChanged, this, &BlueDevilDaemon::obexOperationalChanged);
0194 }
0195 
0196 void BlueDevilDaemon::operationalChanged(bool operational)
0197 {
0198     qCDebug(BLUEDEVIL_KDED_LOG) << "Bluetooth operational changed" << operational;
0199 
0200     if (operational) {
0201         BluezQt::PendingCall *rCall = d->m_manager->registerAgent(d->m_bluezAgent);
0202         connect(rCall, &BluezQt::PendingCall::finished, this, &BlueDevilDaemon::agentRegisted);
0203 
0204         BluezQt::PendingCall *rdCall = d->m_manager->requestDefaultAgent(d->m_bluezAgent);
0205         connect(rdCall, &BluezQt::PendingCall::finished, this, &BlueDevilDaemon::agentRequestedDefault);
0206     } else {
0207         // Attempt to start bluetoothd
0208         BluezQt::Manager::startService();
0209     }
0210 }
0211 
0212 void BlueDevilDaemon::obexOperationalChanged(bool operational)
0213 {
0214     qCDebug(BLUEDEVIL_KDED_LOG) << "ObexManager operational changed" << operational;
0215 
0216     if (operational) {
0217         BluezQt::PendingCall *call = d->m_obexManager->registerAgent(d->m_obexAgent);
0218         connect(call, &BluezQt::PendingCall::finished, this, &BlueDevilDaemon::obexAgentRegistered);
0219     } else {
0220         // Attempt to start obexd
0221         BluezQt::ObexManager::startService();
0222     }
0223 }
0224 
0225 void BlueDevilDaemon::agentRegisted(BluezQt::PendingCall *call)
0226 {
0227     if (call->error()) {
0228         qCWarning(BLUEDEVIL_KDED_LOG) << "Error registering Agent" << call->errorText();
0229     } else {
0230         qCDebug(BLUEDEVIL_KDED_LOG) << "Agent registered";
0231     }
0232 }
0233 
0234 void BlueDevilDaemon::agentRequestedDefault(BluezQt::PendingCall *call)
0235 {
0236     if (call->error()) {
0237         qCWarning(BLUEDEVIL_KDED_LOG) << "Error requesting default Agent" << call->errorText();
0238     } else {
0239         qCDebug(BLUEDEVIL_KDED_LOG) << "Requested default Agent";
0240     }
0241 }
0242 
0243 void BlueDevilDaemon::obexAgentRegistered(BluezQt::PendingCall *call)
0244 {
0245     if (call->error()) {
0246         qCWarning(BLUEDEVIL_KDED_LOG) << "Error registering ObexAgent" << call->errorText();
0247     } else {
0248         qCDebug(BLUEDEVIL_KDED_LOG) << "ObexAgent registered";
0249     }
0250 }
0251 
0252 DeviceInfo BlueDevilDaemon::deviceToInfo(BluezQt::DevicePtr device) const
0253 {
0254     DeviceInfo info;
0255 
0256     if (!device) {
0257         return info;
0258     }
0259 
0260     info[QStringLiteral("name")] = device->name();
0261     info[QStringLiteral("icon")] = device->icon();
0262     info[QStringLiteral("address")] = device->address();
0263     info[QStringLiteral("UBI")] = device->ubi();
0264     info[QStringLiteral("UUIDs")] = device->uuids().join(QLatin1Char(','));
0265 
0266     return info;
0267 }
0268 
0269 #include "bluedevildaemon.moc"
0270 
0271 #include "moc_bluedevildaemon.cpp"