File indexing completed on 2024-07-21 03:38:19

0001 /*
0002  * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 #include "deviceinterface.h"
0008 #include "batteryinterface.h"
0009 #include "inputinterface.h"
0010 #include "mediaplayerinterface.h"
0011 #include "mediatransportinterface.h"
0012 #include "objectmanager.h"
0013 
0014 #include <QDBusArgument>
0015 #include <QDBusConnection>
0016 #include <QDBusMessage>
0017 
0018 static const QLatin1String MediaPlayerUuid("0000110E-0000-1000-8000-00805F9B34FB");
0019 static const QLatin1String MediaTransportUuid("0000110B-0000-1000-8000-00805F9B34FB");
0020 
0021 // DeviceObject
0022 DeviceObject::DeviceObject(const QDBusObjectPath &path, QObject *parent)
0023     : QObject(parent)
0024 {
0025     QDBusConnection::sessionBus().registerObject(path.path(), this);
0026 }
0027 
0028 // DeviceInterface
0029 DeviceInterface::DeviceInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent)
0030     : QDBusAbstractAdaptor(parent)
0031 {
0032     setPath(path);
0033     setObjectParent(parent);
0034     setProperties(properties);
0035     setName(QStringLiteral("org.bluez.Device1"));
0036 
0037     // Alias needs special handling
0038     setAlias(properties.value(QStringLiteral("Alias")).toString());
0039 
0040     // Create Battery1
0041     if (properties.contains(QStringLiteral("Battery"))) {
0042         const QVariantMap &inputProps = qdbus_cast<QVariantMap>(properties.value(QStringLiteral("Battery")));
0043         BatteryInterface *input = new BatteryInterface(path, inputProps, parent);
0044 
0045         ObjectManager *manager = ObjectManager::self();
0046         manager->addObject(input);
0047 
0048         QVariantMap props = properties;
0049         props.remove(QStringLiteral("Battery"));
0050         setProperties(props);
0051     }
0052 
0053     // Create Input1
0054     if (properties.contains(QStringLiteral("Input"))) {
0055         const QVariantMap &inputProps = qdbus_cast<QVariantMap>(properties.value(QStringLiteral("Input")));
0056         InputInterface *input = new InputInterface(path, inputProps, parent);
0057 
0058         ObjectManager *manager = ObjectManager::self();
0059         manager->addObject(input);
0060 
0061         QVariantMap props = properties;
0062         props.remove(QStringLiteral("Input"));
0063         setProperties(props);
0064     }
0065 }
0066 
0067 QString DeviceInterface::address() const
0068 {
0069     return Object::property(QStringLiteral("Address")).toString();
0070 }
0071 
0072 QString DeviceInterface::name() const
0073 {
0074     return Object::property(QStringLiteral("Name")).toString();
0075 }
0076 
0077 QString DeviceInterface::alias() const
0078 {
0079     return Object::property(QStringLiteral("Alias")).toString();
0080 }
0081 
0082 void DeviceInterface::setAlias(const QString &alias)
0083 {
0084     Object::changeProperty(QStringLiteral("Alias"), alias.isEmpty() ? name() : alias);
0085 }
0086 
0087 QString DeviceInterface::icon() const
0088 {
0089     return Object::property(QStringLiteral("Icon")).toString();
0090 }
0091 
0092 quint32 DeviceInterface::deviceClass() const
0093 {
0094     return Object::property(QStringLiteral("Class")).toUInt();
0095 }
0096 
0097 quint16 DeviceInterface::appearance() const
0098 {
0099     return Object::property(QStringLiteral("Appearance")).toUInt();
0100 }
0101 
0102 bool DeviceInterface::paired() const
0103 {
0104     return Object::property(QStringLiteral("Paired")).toBool();
0105 }
0106 
0107 bool DeviceInterface::connected() const
0108 {
0109     return Object::property(QStringLiteral("Connected")).toBool();
0110 }
0111 
0112 bool DeviceInterface::trusted() const
0113 {
0114     return Object::property(QStringLiteral("Trusted")).toBool();
0115 }
0116 
0117 void DeviceInterface::setTrusted(bool trusted)
0118 {
0119     Object::changeProperty(QStringLiteral("Trusted"), trusted);
0120 }
0121 
0122 bool DeviceInterface::blocked() const
0123 {
0124     return Object::property(QStringLiteral("Blocked")).toBool();
0125 }
0126 
0127 void DeviceInterface::setBlocked(bool blocked)
0128 {
0129     Object::changeProperty(QStringLiteral("Blocked"), blocked);
0130 }
0131 
0132 QDBusObjectPath DeviceInterface::adapter() const
0133 {
0134     return Object::property(QStringLiteral("Adapter")).value<QDBusObjectPath>();
0135 }
0136 
0137 bool DeviceInterface::legacyPairing() const
0138 {
0139     return Object::property(QStringLiteral("LegacyPairing")).toBool();
0140 }
0141 
0142 qint16 DeviceInterface::rssi() const
0143 {
0144     return Object::property(QStringLiteral("RSSI")).toInt();
0145 }
0146 
0147 QStringList DeviceInterface::uuids() const
0148 {
0149     return Object::property(QStringLiteral("UUIDs")).toStringList();
0150 }
0151 
0152 QString DeviceInterface::modalias() const
0153 {
0154     return Object::property(QStringLiteral("Modalias")).toString();
0155 }
0156 
0157 MediaTransportInterface *DeviceInterface::mediaTransport() const
0158 {
0159     return m_mediaTransport;
0160 }
0161 
0162 void DeviceInterface::Connect()
0163 {
0164     if (uuids().contains(MediaPlayerUuid)) {
0165         connectMediaPlayer();
0166     }
0167 
0168     if (uuids().contains(MediaTransportUuid)) {
0169         connectMediaTransport();
0170     }
0171 
0172     Object::changeProperty(QStringLiteral("Connected"), true);
0173 }
0174 
0175 void DeviceInterface::Disconnect()
0176 {
0177     if (uuids().contains(MediaPlayerUuid)) {
0178         disconnectMediaPlayer();
0179     }
0180 
0181     if (uuids().contains(MediaTransportUuid)) {
0182         disconnectMediaTransport();
0183     }
0184 
0185     Object::changeProperty(QStringLiteral("Connected"), false);
0186 }
0187 
0188 void DeviceInterface::ConnectProfile(const QString &uuid, const QDBusMessage &msg)
0189 {
0190     if (!uuids().contains(uuid)) {
0191         QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.DoesNotExist"), QStringLiteral("Profile UUID not supported"));
0192         QDBusConnection::sessionBus().send(error);
0193         return;
0194     }
0195 
0196     if (m_connectedUuids.contains(uuid)) {
0197         QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.AlreadyConnected"), QStringLiteral("Profile already connected"));
0198         QDBusConnection::sessionBus().send(error);
0199         return;
0200     }
0201 
0202     if (uuid == MediaPlayerUuid) {
0203         connectMediaPlayer();
0204     } else if (uuid == MediaTransportUuid) {
0205         connectMediaTransport();
0206     } else {
0207         Q_UNIMPLEMENTED();
0208     }
0209 
0210     Object::changeProperty(QStringLiteral("Connected"), true);
0211 }
0212 
0213 void DeviceInterface::DisconnectProfile(const QString &uuid, const QDBusMessage &msg)
0214 {
0215     if (!uuids().contains(uuid)) {
0216         QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.DoesNotExist"), QStringLiteral("Profile UUID not supported"));
0217         QDBusConnection::sessionBus().send(error);
0218         return;
0219     }
0220 
0221     if (!m_connectedUuids.contains(uuid)) {
0222         QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.NotConnected"), QStringLiteral("Profile not connected"));
0223         QDBusConnection::sessionBus().send(error);
0224         return;
0225     }
0226 
0227     if (uuid == MediaPlayerUuid) {
0228         disconnectMediaPlayer();
0229     } else if (uuid == MediaTransportUuid) {
0230         disconnectMediaTransport();
0231     } else {
0232         Q_UNIMPLEMENTED();
0233     }
0234 
0235     Object::changeProperty(QStringLiteral("Connected"), false);
0236 }
0237 
0238 void DeviceInterface::Pair()
0239 {
0240     Q_UNIMPLEMENTED();
0241 }
0242 
0243 void DeviceInterface::CancelPairing()
0244 {
0245     Q_UNIMPLEMENTED();
0246 }
0247 
0248 void DeviceInterface::connectMediaPlayer()
0249 {
0250     const QVariantMap &properties = qdbus_cast<QVariantMap>(Object::property(QStringLiteral("MediaPlayer")));
0251     const QDBusObjectPath &path = properties.value(QStringLiteral("Path")).value<QDBusObjectPath>();
0252     QVariantMap props = properties;
0253     props.remove(QStringLiteral("Path"));
0254 
0255     MediaPlayerObject *mediaPlayerObj = new MediaPlayerObject(path);
0256     m_mediaPlayer = new MediaPlayerInterface(path, props, mediaPlayerObj);
0257 
0258     ObjectManager *manager = ObjectManager::self();
0259     manager->addObject(m_mediaPlayer);
0260     manager->addAutoDeleteObject(mediaPlayerObj);
0261 
0262     m_connectedUuids.append(MediaPlayerUuid);
0263 }
0264 
0265 void DeviceInterface::disconnectMediaPlayer()
0266 {
0267     ObjectManager *manager = ObjectManager::self();
0268     manager->removeObject(m_mediaPlayer);
0269     m_connectedUuids.removeOne(MediaPlayerUuid);
0270 
0271     m_mediaPlayer = nullptr;
0272 }
0273 
0274 void DeviceInterface::connectMediaTransport()
0275 {
0276     const QVariantMap &properties = qdbus_cast<QVariantMap>(Object::property(QStringLiteral("MediaTransport")));
0277     const QDBusObjectPath &path = properties.value(QStringLiteral("Path")).value<QDBusObjectPath>();
0278     QVariantMap props = properties;
0279     props.remove(QStringLiteral("Path"));
0280 
0281     MediaTransportObject *transportObj = new MediaTransportObject(path);
0282     m_mediaTransport = new MediaTransportInterface(path, props, transportObj);
0283 
0284     ObjectManager *manager = ObjectManager::self();
0285     manager->addObject(m_mediaTransport);
0286     manager->addAutoDeleteObject(transportObj);
0287 
0288     m_connectedUuids.append(MediaTransportUuid);
0289 }
0290 
0291 void DeviceInterface::disconnectMediaTransport()
0292 {
0293     ObjectManager *manager = ObjectManager::self();
0294     manager->removeObject(m_mediaTransport);
0295     m_connectedUuids.removeOne(MediaTransportUuid);
0296 
0297     m_mediaTransport = nullptr;
0298 }
0299 
0300 #include "moc_deviceinterface.cpp"