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

0001 /*
0002  * SPDX-FileCopyrightText: 2018-2019 Daniel Vrátil <dvratil@kde.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "manager.h"
0008 #include "dbushelper.h"
0009 #include "device.h"
0010 #include "libkbolt_debug.h"
0011 #include "managerinterface.h"
0012 
0013 using namespace Bolt;
0014 
0015 using ManagerInterface = org::freedesktop::bolt1::Manager;
0016 
0017 Manager::Manager(QObject *parent)
0018     : QObject(parent)
0019     , mInterface(std::make_unique<ManagerInterface>(DBusHelper::serviceName(), QStringLiteral("/org/freedesktop/bolt"), DBusHelper::connection()))
0020 {
0021     qDBusRegisterMetaType<QDBusObjectPath>();
0022 
0023     if (!mInterface->isValid()) {
0024         qCWarning(log_libkbolt, "Failed to connect to Bolt manager DBus interface: %s", qUtf8Printable(mInterface->lastError().message()));
0025         return;
0026     }
0027 
0028     connect(mInterface.get(), &ManagerInterface::DeviceAdded, this, [this](const QDBusObjectPath &path) {
0029         if (auto device = Device::create(path)) {
0030             mDevices.push_back(device);
0031             qCDebug(log_libkbolt,
0032                     "New Thunderbolt device %s (%s) added, status=%s",
0033                     qUtf8Printable(device->uid()),
0034                     qUtf8Printable(device->name()),
0035                     qUtf8Printable(statusToString(device->status())));
0036             Q_EMIT deviceAdded(device);
0037         }
0038     });
0039     connect(mInterface.get(), &ManagerInterface::DeviceRemoved, this, [this](const QDBusObjectPath &path) {
0040         if (auto device = this->device(path)) {
0041             mDevices.removeOne(device);
0042             qCDebug(log_libkbolt, "Thunderbolt Device %s (%s) removed", qUtf8Printable(device->uid()), qUtf8Printable(device->name()));
0043             Q_EMIT deviceRemoved(device);
0044         }
0045     });
0046 
0047     const auto devicePaths = mInterface->ListDevices().argumentAt<0>();
0048     for (const auto &devicePath : devicePaths) {
0049         if (auto device = Device::create(devicePath)) {
0050             qCDebug(log_libkbolt,
0051                     "Discovered Thunderbolt device %s (%s), status=%s",
0052                     qUtf8Printable(device->uid()),
0053                     qUtf8Printable(device->name()),
0054                     qUtf8Printable(statusToString(device->status())));
0055             mDevices.push_back(device);
0056         }
0057     }
0058 }
0059 
0060 Manager::~Manager() = default;
0061 
0062 bool Manager::isAvailable() const
0063 {
0064     return mInterface.get() && mInterface->isValid();
0065 }
0066 
0067 uint Manager::version() const
0068 {
0069     return mInterface->version();
0070 }
0071 
0072 bool Manager::isProbing() const
0073 {
0074     return mInterface->probing();
0075 }
0076 
0077 Policy Manager::defaultPolicy() const
0078 {
0079     const auto policy = mInterface->defaultPolicy();
0080     if (!mInterface->isValid() || policy.isEmpty()) {
0081         return Policy::Unknown;
0082     }
0083     return policyFromString(policy);
0084 }
0085 
0086 Security Manager::securityLevel() const
0087 {
0088     const auto level = mInterface->securityLevel();
0089     if (!mInterface->isValid() || level.isEmpty()) {
0090         return Security::Unknown;
0091     }
0092     return securityFromString(level);
0093 }
0094 
0095 AuthMode Manager::authMode() const
0096 {
0097     const auto mode = mInterface->authMode();
0098     if (!mInterface->isValid() || mode.isEmpty()) {
0099         return AuthMode::Disabled;
0100     }
0101     return authModeFromString(mode);
0102 }
0103 
0104 void Manager::setAuthMode(AuthMode mode)
0105 {
0106     mInterface->setAuthMode(authModeToString(mode));
0107     Q_EMIT authModeChanged(mode);
0108 }
0109 
0110 QSharedPointer<Device> Manager::device(std::function<bool(const QSharedPointer<Device> &)> &&match) const
0111 {
0112     auto device = std::find_if(mDevices.cbegin(), mDevices.cend(), std::move(match));
0113     return device == mDevices.cend() ? QSharedPointer<Device>() : *device;
0114 }
0115 
0116 QSharedPointer<Device> Manager::device(const QString &uid) const
0117 {
0118     return device([uid](const auto &device) {
0119         return device->uid() == uid;
0120     });
0121 }
0122 
0123 QSharedPointer<Device> Manager::device(const QDBusObjectPath &path) const
0124 {
0125     return device([path](const auto &device) {
0126         return device->dbusPath() == path;
0127     });
0128 }
0129 
0130 QList<QSharedPointer<Device>> Manager::devices() const
0131 {
0132     return mDevices;
0133 }
0134 
0135 void Manager::enrollDevice(const QString &uid,
0136                            Policy policy,
0137                            AuthFlags authFlags,
0138                            std::function<void()> successCallback,
0139                            std::function<void(const QString &)> errorCallback)
0140 {
0141     qCDebug(log_libkbolt,
0142             "Enrolling Thunderbolt device %s with policy %s and flags %s",
0143             qUtf8Printable(uid),
0144             qUtf8Printable(policyToString(policy)),
0145             qUtf8Printable(authFlagsToString(authFlags)));
0146 
0147     auto device = this->device(uid);
0148     if (device) {
0149         device->setStatusOverride(Status::Authorizing);
0150     } else {
0151         qCWarning(log_libkbolt, "Found no matching Thunderbolt device object for uid %s", qUtf8Printable(uid));
0152     }
0153 
0154     DBusHelper::call<QString, QString, QString>(
0155         mInterface.get(),
0156         QStringLiteral("EnrollDevice"),
0157         uid,
0158         policyToString(policy),
0159         authFlagsToString(authFlags),
0160         [uid, device, policy, authFlags, cb = std::move(successCallback)]() {
0161             qCDebug(log_libkbolt, "Thunderbolt device %s was successfully enrolled", qUtf8Printable(uid));
0162             if (device) {
0163                 device->clearStatusOverride();
0164                 Q_EMIT device->storedChanged(true);
0165                 Q_EMIT device->policyChanged(policy);
0166                 Q_EMIT device->authFlagsChanged(authFlags);
0167             }
0168             if (cb) {
0169                 cb();
0170             }
0171         },
0172         [uid, device, cb = std::move(errorCallback)](const QString &error) {
0173             qCWarning(log_libkbolt, "Failed to enroll Thunderbolt device %s: %s", qUtf8Printable(uid), qUtf8Printable(error));
0174             if (device) {
0175                 device->setStatusOverride(Status::AuthError);
0176             }
0177             if (cb) {
0178                 cb(error);
0179             }
0180         },
0181         this);
0182 }
0183 
0184 void Manager::forgetDevice(const QString &uid, std::function<void()> successCallback, std::function<void(const QString &)> errorCallback)
0185 {
0186     qCDebug(log_libkbolt, "Forgetting Thunderbolt device %s", qUtf8Printable(uid));
0187 
0188     DBusHelper::call<QString>(
0189         mInterface.get(),
0190         QStringLiteral("ForgetDevice"),
0191         uid,
0192         [this, uid, cb = std::move(successCallback)]() {
0193             qCDebug(log_libkbolt, "Thunderbolt device %s was successfully forgotten", qUtf8Printable(uid));
0194             if (auto device = this->device(uid)) {
0195                 device->clearStatusOverride();
0196                 Q_EMIT device->storedChanged(false);
0197                 Q_EMIT device->authFlagsChanged(Auth::None);
0198                 Q_EMIT device->policyChanged(Policy::Auto);
0199             }
0200             if (cb) {
0201                 cb();
0202             }
0203         },
0204         [this, uid, cb = std::move(errorCallback)](const QString &error) {
0205             qCWarning(log_libkbolt, "Failed to forget Thunderbolt device %s: %s", qUtf8Printable(uid), qUtf8Printable(error));
0206             if (auto device = this->device(uid)) {
0207                 device->setStatusOverride(Status::AuthError);
0208             }
0209             if (cb) {
0210                 cb(error);
0211             }
0212         },
0213         this);
0214 }
0215 
0216 #include "moc_manager.cpp"