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"