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

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 "device.h"
0008 #include "dbushelper.h"
0009 #include "deviceinterface.h"
0010 #include "libkbolt_debug.h"
0011 
0012 #include <stdexcept>
0013 
0014 using namespace Bolt;
0015 
0016 using DeviceInterface = org::freedesktop::bolt1::Device;
0017 
0018 class DBusException : public std::runtime_error
0019 {
0020 public:
0021     DBusException(const QString &what)
0022         : std::runtime_error(what.toStdString())
0023     {
0024     }
0025 };
0026 
0027 Device::Device(QObject *parent)
0028     : QObject(parent)
0029 {
0030 }
0031 
0032 Device::Device(const QDBusObjectPath &path, QObject *parent)
0033     : QObject(parent)
0034     , mInterface(std::make_unique<DeviceInterface>(DBusHelper::serviceName(), path.path(), DBusHelper::connection()))
0035     , mDBusPath(path)
0036 {
0037     if (!mInterface->isValid()) {
0038         throw DBusException(QStringLiteral("Failed to obtain DBus interface for device %1: %2").arg(path.path(), mInterface->lastError().message()));
0039     }
0040 
0041     // cache UID in case the we still need to identify the device, even if it's
0042     // gone on DBus
0043     mUid = mInterface->uid();
0044 }
0045 
0046 Device::~Device() = default;
0047 
0048 QSharedPointer<Device> Device::create(const QDBusObjectPath &path)
0049 {
0050     try {
0051         return QSharedPointer<Device>::create(path);
0052     } catch (const DBusException &e) {
0053         qCWarning(log_libkbolt, "%s", e.what());
0054         return {};
0055     }
0056 }
0057 
0058 QDBusObjectPath Device::dbusPath() const
0059 {
0060     return mDBusPath;
0061 }
0062 
0063 QString Device::uid() const
0064 {
0065     return mUid;
0066 }
0067 
0068 QString Device::name() const
0069 {
0070     return mInterface->name();
0071 }
0072 
0073 QString Device::vendor() const
0074 {
0075     return mInterface->vendor();
0076 }
0077 
0078 Type Device::type() const
0079 {
0080     const auto val = mInterface->type();
0081     return val.isEmpty() ? Type::Unknown : typeFromString(val);
0082 }
0083 
0084 Status Device::status() const
0085 {
0086     if (mStatusOverride == Status::Unknown) {
0087         const auto val = mInterface->status();
0088         return val.isEmpty() ? Status::Unknown : statusFromString(val);
0089     } else {
0090         return mStatusOverride;
0091     }
0092 }
0093 
0094 void Device::setStatusOverride(Status status)
0095 {
0096     if (mStatusOverride != status) {
0097         mStatusOverride = status;
0098         Q_EMIT statusChanged(status);
0099     }
0100 }
0101 
0102 void Device::clearStatusOverride()
0103 {
0104     setStatusOverride(Status::Unknown);
0105 }
0106 
0107 AuthFlags Device::authFlags() const
0108 {
0109     const auto val = mInterface->authFlags();
0110     return val.isEmpty() ? Auth::None : authFlagsFromString(val);
0111 }
0112 
0113 QString Device::parent() const
0114 {
0115     return mInterface->parentUid();
0116 }
0117 
0118 QString Device::sysfsPath() const
0119 {
0120     return mInterface->sysfsPath();
0121 }
0122 
0123 QDateTime Device::connectTime() const
0124 {
0125     const auto val = mInterface->connectTime();
0126     return val == 0 ? QDateTime() : QDateTime::fromSecsSinceEpoch(val);
0127 }
0128 
0129 QDateTime Device::authorizeTime() const
0130 {
0131     const auto val = mInterface->authorizeTime();
0132     return val == 0 ? QDateTime() : QDateTime::fromSecsSinceEpoch(val);
0133 }
0134 
0135 bool Device::stored() const
0136 {
0137     return mInterface ? mInterface->stored() : false;
0138 }
0139 
0140 Policy Device::policy() const
0141 {
0142     const auto val = mInterface->policy();
0143     return val.isEmpty() ? Policy::Unknown : policyFromString(val);
0144 }
0145 
0146 KeyState Device::keyState() const
0147 {
0148     const auto val = mInterface->key();
0149     return val.isEmpty() ? KeyState::Unknown : keyStateFromString(val);
0150 }
0151 
0152 QDateTime Device::storeTime() const
0153 {
0154     const auto val = mInterface->storeTime();
0155     return val == 0 ? QDateTime() : QDateTime::fromSecsSinceEpoch(val);
0156 }
0157 
0158 QString Device::label() const
0159 {
0160     return mInterface->label();
0161 }
0162 
0163 void Device::authorize(AuthFlags authFlags, std::function<void()> successCb, std::function<void(const QString &)> errorCb)
0164 {
0165     qCDebug(log_libkbolt, "Authorizing device %s with auth flags %s", qUtf8Printable(mUid), qUtf8Printable(authFlagsToString(authFlags)));
0166 
0167     setStatusOverride(Status::Authorizing);
0168     DBusHelper::call<QString>(
0169         mInterface.get(),
0170         QStringLiteral("Authorize"),
0171         authFlagsToString(authFlags),
0172         [this, cb = std::move(successCb)]() {
0173             qCDebug(log_libkbolt, "Device %s was successfully authorized", qUtf8Printable(mUid));
0174             clearStatusOverride();
0175             if (cb) {
0176                 cb();
0177             }
0178         },
0179         [this, cb = std::move(errorCb)](const QString &error) {
0180             qCWarning(log_libkbolt, "Failed to authorize device %s: %s", qUtf8Printable(mUid), qUtf8Printable(error));
0181             setStatusOverride(Status::AuthError);
0182             if (cb) {
0183                 cb(error);
0184             }
0185         },
0186         this);
0187 }
0188 
0189 #include "moc_device.cpp"