File indexing completed on 2024-04-28 15:17:53

0001 /*
0002  * BluezQt - Asynchronous BlueZ wrapper library
0003  *
0004  * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #ifndef BLUEZQT_MANAGER_H
0010 #define BLUEZQT_MANAGER_H
0011 
0012 #include <QObject>
0013 
0014 #include "adapter.h"
0015 #include "bluezqt_export.h"
0016 #include "media.h"
0017 #include "rfkill.h"
0018 
0019 namespace BluezQt
0020 {
0021 class Device;
0022 class Agent;
0023 class Profile;
0024 class PendingCall;
0025 class InitManagerJob;
0026 
0027 /**
0028  * @class BluezQt::Manager manager.h <BluezQt/Manager>
0029  *
0030  * Bluetooth manager.
0031  *
0032  * The entry point to communicate with system BlueZ daemon.
0033  *
0034  * The typical usecase is to work with usableAdapter() (any powered adapter),
0035  * but it is also possible to use specific adapter.
0036  *
0037  * You must call init() before other functions can be used.
0038  *
0039  * The only functions that can be used before initialization are two rfkill-related
0040  * functions: isBluetoothBlocked() and setBluetoothBlocked().
0041  *
0042  * Example use in C++ code:
0043  * @code
0044  * BluezQt::Manager *manager = new BluezQt::Manager();
0045  * BluezQt::InitManagerJob *job = manager->init();
0046  * job->start();
0047  * connect(job, &BluezQt::InitManagerJob::result, ...);
0048  * @endcode
0049  *
0050  * In QML, manager is a singleton and initialization is started when first using
0051  * the manager. You don't need to track initialized state, just use property binding.
0052  *
0053  * Example use in QML code:
0054  * @code
0055  * import QtQuick 2.2
0056  * import org.kde.bluezqt 1.0 as BluezQt
0057  *
0058  * Item {
0059  *     property QtObject manager : BluezQt.Manager
0060  *     property devicesCount : manager.devices.length
0061  *     property adaptersCount : manager.adapters.length
0062  *
0063  *     Component.onCompleted: {
0064  *         console.log("Manager operational:", manager.operational)
0065  *     }
0066  * }
0067  * @endcode
0068  *
0069  * @note All communication with BlueZ daemon happens asynchronously. Almost all methods
0070  *       returns PendingCall to help track the call progress and to check for any errors.
0071  *
0072  * @note If manager is not operational, all methods that returns a PendingCall will fail
0073  *       with PendingCall::InternalError.
0074  *
0075  * @see InitManagerJob
0076  */
0077 class BLUEZQT_EXPORT Manager : public QObject
0078 {
0079     Q_OBJECT
0080 
0081     Q_PROPERTY(bool initialized READ isInitialized)
0082     Q_PROPERTY(bool operational READ isOperational NOTIFY operationalChanged)
0083     Q_PROPERTY(bool bluetoothOperational READ isBluetoothOperational NOTIFY bluetoothOperationalChanged)
0084     Q_PROPERTY(bool bluetoothBlocked READ isBluetoothBlocked WRITE setBluetoothBlocked NOTIFY bluetoothBlockedChanged)
0085     Q_PROPERTY(AdapterPtr usableAdapter READ usableAdapter NOTIFY usableAdapterChanged)
0086     Q_PROPERTY(QList<AdapterPtr> adapters READ adapters)
0087     Q_PROPERTY(QList<DevicePtr> devices READ devices)
0088     Q_PROPERTY(Rfkill *rfkill READ rfkill CONSTANT)
0089 
0090 public:
0091     /**
0092      * Creates a new Manager object.
0093      *
0094      * @param parent
0095      */
0096     explicit Manager(QObject *parent = nullptr);
0097 
0098     /**
0099      * Destroys a Manager object.
0100      */
0101     ~Manager() override;
0102 
0103     /**
0104      * Creates a new init job.
0105      *
0106      * @return init manager job
0107      */
0108     InitManagerJob *init();
0109 
0110     /**
0111      * Returns whether the manager is initialized.
0112      *
0113      * @return true if manager is initialized
0114      */
0115     bool isInitialized() const;
0116 
0117     /**
0118      * Returns whether the manager is operational.
0119      *
0120      * The manager is operational when initialization was successful and
0121      * BlueZ system daemon is running.
0122      *
0123      * @return true if manager is operational
0124      */
0125     bool isOperational() const;
0126 
0127     /**
0128      * Returns whether Bluetooth is operational.
0129      *
0130      * Bluetooth is operational when manager is operational and there is
0131      * a valid usable adapter.
0132      *
0133      * @return true if Bluetooth is operational
0134      */
0135     bool isBluetoothOperational() const;
0136 
0137     /**
0138      * Returns whether Bluetooth is blocked.
0139      *
0140      * Bluetooth is blocked if rfkill state for Bluetooth is either
0141      * SOFT_BLOCKED or HARD_BLOCKED.
0142      *
0143      * @note This requires read access to /dev/rfkill.
0144      *
0145      * @return true if Bluetooth is blocked
0146      */
0147     bool isBluetoothBlocked() const;
0148 
0149     /**
0150      * Sets a Bluetooth blocked state.
0151      *
0152      * This may fail either due to insufficient permissions or
0153      * because rfkill state is HARD_BLOCKED. In that case,
0154      * this function returns false.
0155      *
0156      * @note This requires write access to /dev/rfkill.
0157      *
0158      * @return true if unblocking rfkill devices succeeded
0159      */
0160     bool setBluetoothBlocked(bool blocked);
0161 
0162     /**
0163      * Returns a usable adapter.
0164      *
0165      * Usable adapter is any adapter that is currently powered on.
0166      *
0167      * @return usable adapter
0168      */
0169     AdapterPtr usableAdapter() const;
0170 
0171     /**
0172      * Returns a list of all adapters.
0173      *
0174      * @return list of adapters
0175      */
0176     QList<AdapterPtr> adapters() const;
0177 
0178     /**
0179      * Returns a list of all devices.
0180      *
0181      * @return list of devices
0182      */
0183     QList<DevicePtr> devices() const;
0184 
0185     /**
0186      * Attempts to start org.bluez service by D-Bus activation.
0187      *
0188      * Possible return values are 1 if the service was started,
0189      * 2 if the service is already running or error if the service
0190      * could not be started.
0191      *
0192      * @return quint32 pending call
0193      */
0194     static PendingCall *startService();
0195 
0196     /**
0197      * Returns an adapter for specified address.
0198      *
0199      * @param address address of adapter (eg. "1C:E5:C3:BC:94:7E")
0200      * @return null if there is no adapter with specified address
0201      */
0202     AdapterPtr adapterForAddress(const QString &address) const;
0203 
0204     /**
0205      * Returns an adapter for specified UBI.
0206      *
0207      * @param ubi UBI of adapter (eg. "/org/bluez/hci0")
0208      * @return null if there is no adapter with specified UBI
0209      */
0210     AdapterPtr adapterForUbi(const QString &ubi) const;
0211 
0212     /**
0213      * Returns a device for specified address.
0214      *
0215      * @note There may be more devices with the same address (same device
0216      *       in multiple adapters). In this case, the first found device will
0217      *       be returned while preferring powered adapters in search.
0218      *
0219      * @param address address of device (eg. "40:79:6A:0C:39:75")
0220      * @return null if there is no device with specified address
0221      */
0222     DevicePtr deviceForAddress(const QString &address) const;
0223 
0224     /**
0225      * Returns a device for specified UBI.
0226      *
0227      * @param ubi UBI of device (eg. "/org/bluez/hci0/dev_40_79_6A_0C_39_75")
0228      * @return null if there is no device with specified UBI
0229      */
0230     DevicePtr deviceForUbi(const QString &ubi) const;
0231 
0232     /**
0233      * Registers agent.
0234      *
0235      * This agent will be used for for all actions triggered by the application.
0236      * Eg. show a PIN code in pairing process.
0237      *
0238      * Possible errors: PendingCall::InvalidArguments, PendingCall::AlreadyExists
0239      *
0240      * @param agent agent to be registered
0241      * @return void pending call
0242      */
0243     PendingCall *registerAgent(Agent *agent);
0244 
0245     /**
0246      * Unregisters agent.
0247      *
0248      * Possible errors: PendingCall::DoesNotExist
0249      *
0250      * @param agent agent to be unregistered
0251      * @return void pending call
0252      */
0253     PendingCall *unregisterAgent(Agent *agent);
0254 
0255     /**
0256      * Requests default agent.
0257      *
0258      * This requests to make the application agent the default agent.
0259      *
0260      * Possible errors: PendingCall::DoesNotExist
0261      *
0262      * @param agent registered agent
0263      * @return void pending call
0264      */
0265     PendingCall *requestDefaultAgent(Agent *agent);
0266 
0267     /**
0268      * Registers profile.
0269      *
0270      * Possible errors: PendingCall::InvalidArguments, PendingCall::AlreadyExists
0271      *
0272      * @param profile profile to be registered
0273      * @return void pending call
0274      */
0275     PendingCall *registerProfile(Profile *profile);
0276 
0277     /**
0278      * Unregisters profile.
0279      *
0280      * Possible errors: PendingCall::DoesNotExist
0281      *
0282      * @param profile profile to be unregistered
0283      * @return void pending call
0284      */
0285     PendingCall *unregisterProfile(Profile *profile);
0286 
0287 #if BLUEZQT_ENABLE_DEPRECATED_SINCE(5, 57)
0288     /**
0289      * Returns the media interface.
0290      *
0291      * @return media
0292      * @deprecated since 5.57, use Adapter::media() instead.
0293      */
0294     BLUEZQT_DEPRECATED_VERSION(5, 57, "Use Adapter::media()")
0295     MediaPtr media() const;
0296 #endif
0297 
0298     Rfkill *rfkill() const;
0299 
0300 Q_SIGNALS:
0301     /**
0302      * Indicates that operational state have changed.
0303      */
0304     void operationalChanged(bool operational);
0305 
0306     /**
0307      * Indicates that Bluetooth operational state have changed.
0308      */
0309     void bluetoothOperationalChanged(bool operational);
0310 
0311     /**
0312      * Indicates that Bluetooth blocked state have changed.
0313      */
0314     void bluetoothBlockedChanged(bool blocked);
0315 
0316     /**
0317      * Indicates that adapter was added.
0318      */
0319     void adapterAdded(AdapterPtr adapter);
0320 
0321     /**
0322      * Indicates that adapter was removed.
0323      */
0324     void adapterRemoved(AdapterPtr adapter);
0325 
0326     /**
0327      * Indicates that at least one of the adapter's properties have changed.
0328      */
0329     void adapterChanged(AdapterPtr adapter);
0330 
0331     /**
0332      * Indicates that a new device was added (eg. found by discovery).
0333      */
0334     void deviceAdded(DevicePtr device);
0335 
0336     /**
0337      * Indicates that a device was removed.
0338      */
0339     void deviceRemoved(DevicePtr device);
0340 
0341     /**
0342      * Indicates that at least one of the device's properties have changed.
0343      */
0344     void deviceChanged(DevicePtr device);
0345 
0346     /**
0347      * Indicates that usable adapter have changed.
0348      */
0349     void usableAdapterChanged(AdapterPtr adapter);
0350 
0351     /**
0352      * Indicates that all adapters were removed.
0353      */
0354     void allAdaptersRemoved();
0355 
0356 private:
0357     class ManagerPrivate *const d;
0358 
0359     friend class ManagerPrivate;
0360     friend class InitManagerJobPrivate;
0361 };
0362 
0363 } // namespace BluezQt
0364 
0365 #endif // BLUEZQT_MANAGER_H