1/*
2 * BluezQt - Asynchronous BlueZ wrapper library
3 *
4 * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#ifndef BLUEZQT_MANAGER_H
10#define BLUEZQT_MANAGER_H
11
12#include <QObject>
13
14#include "bluezqt_export.h"
15#include "rfkill.h"
16#include "types.h"
17
18#include <memory>
19
20namespace BluezQt
21{
22class Device;
23class Adapter;
24class Agent;
25class Profile;
26class PendingCall;
27class InitManagerJob;
28
29/*!
30 * \inmodule BluezQt
31 * \class BluezQt::Manager
32 * \inheaderfile BluezQt/Manager
33 * \brief Bluetooth manager.
34 *
35 * The entry point to communicate with system BlueZ daemon.
36 *
37 * The typical usecase is to work with usableAdapter() (any powered adapter),
38 * but it is also possible to use specific adapter.
39 *
40 * You must call init() before other functions can be used.
41 *
42 * The only functions that can be used before initialization are two rfkill-related
43 * functions: isBluetoothBlocked() and setBluetoothBlocked().
44 *
45 * Example use in C++ code:
46 * \code
47 * BluezQt::Manager *manager = new BluezQt::Manager();
48 * BluezQt::InitManagerJob *job = manager->init();
49 * job->start();
50 * connect(job, &BluezQt::InitManagerJob::result, ...);
51 * \endcode
52 *
53 * In QML, manager is a singleton and initialization is started when first using
54 * the manager. You don't need to track initialized state, just use property binding.
55 *
56 * Example use in QML code:
57 * \code
58 * import QtQuick
59 * import org.kde.bluezqt as BluezQt
60 *
61 * Item {
62 * readonly property BluezQt.Manager manager: BluezQt.Manager
63 * property devicesCount: manager.devices.length
64 * property adaptersCount: manager.adapters.length
65 *
66 * Component.onCompleted: {
67 * console.log("Manager operational:", manager.operational)
68 * }
69 * }
70 * \endcode
71 *
72 * \note All communication with BlueZ daemon happens asynchronously. Almost all methods
73 * returns PendingCall to help track the call progress and to check for any errors.
74 *
75 * \note If manager is not operational, all methods that returns a PendingCall will fail
76 * with PendingCall::InternalError.
77 *
78 * \sa InitManagerJob
79 */
80class BLUEZQT_EXPORT Manager : public QObject
81{
82 Q_OBJECT
83
84 /*! \property BluezQt::Manager::initialized */
85 Q_PROPERTY(bool initialized READ isInitialized)
86 /*! \property BluezQt::Manager::operational */
87 Q_PROPERTY(bool operational READ isOperational NOTIFY operationalChanged)
88 /*! \property BluezQt::Manager::bluetoothOperational */
89 Q_PROPERTY(bool bluetoothOperational READ isBluetoothOperational NOTIFY bluetoothOperationalChanged)
90 /*! \property BluezQt::Manager::bluetoothBlocked */
91 Q_PROPERTY(bool bluetoothBlocked READ isBluetoothBlocked WRITE setBluetoothBlocked NOTIFY bluetoothBlockedChanged)
92 /*! \property BluezQt::Manager::usableAdapter */
93 Q_PROPERTY(AdapterPtr usableAdapter READ usableAdapter NOTIFY usableAdapterChanged)
94 /*! \property BluezQt::Manager::adapters */
95 Q_PROPERTY(QList<AdapterPtr> adapters READ adapters)
96 /*! \property BluezQt::Manager::devices */
97 Q_PROPERTY(QList<DevicePtr> devices READ devices)
98 /*! \property BluezQt::Manager::rfkill */
99 Q_PROPERTY(BluezQt::Rfkill *rfkill READ rfkill CONSTANT)
100
101public:
102 /*!
103 * Creates a new Manager object as a child of \a parent.
104 */
105 explicit Manager(QObject *parent = nullptr);
106
107 ~Manager() override;
108
109 /*!
110 * Creates a new init job.
111 */
112 InitManagerJob *init();
113
114 /*!
115 * Returns whether the manager is initialized.
116 */
117 bool isInitialized() const;
118
119 /*!
120 * Returns whether the manager is operational.
121 *
122 * The manager is operational when initialization was successful and
123 * BlueZ system daemon is running.
124 */
125 bool isOperational() const;
126
127 /*!
128 * Returns whether Bluetooth is operational.
129 *
130 * Bluetooth is operational when manager is operational and there is
131 * a valid usable adapter.
132 */
133 bool isBluetoothOperational() const;
134
135 /*!
136 * Returns whether Bluetooth is blocked.
137 *
138 * Bluetooth is blocked if rfkill state for Bluetooth is either
139 * SOFT_BLOCKED or HARD_BLOCKED.
140 *
141 * \note This requires read access to /dev/rfkill.
142 */
143 bool isBluetoothBlocked() const;
144
145 /*!
146 * Sets a Bluetooth blocked state.
147 *
148 * This may fail either due to insufficient permissions or
149 * because rfkill state is HARD_BLOCKED. In that case,
150 * this function returns false.
151 *
152 * \note This requires write access to /dev/rfkill.
153 */
154 void setBluetoothBlocked(bool blocked);
155
156 /*!
157 * Returns a usable adapter.
158 *
159 * A usable adapter is any adapter that is currently powered on.
160 */
161 AdapterPtr usableAdapter() const;
162
163 /*!
164 * Returns a list of all adapters.
165 */
166 QList<AdapterPtr> adapters() const;
167
168 /*!
169 * Returns a list of all devices.
170 */
171 QList<DevicePtr> devices() const;
172
173 /*!
174 * Attempts to start org.bluez service by D-Bus activation.
175 *
176 * Possible return values are 1 if the service was started,
177 * 2 if the service is already running or error if the service
178 * could not be started.
179 *
180 * Returns quint32 pending call.
181 */
182 static PendingCall *startService();
183
184 /*!
185 * Returns an adapter for the specified \a address.
186 *
187 * \a address The address of adapter (eg. "1C:E5:C3:BC:94:7E").
188 */
189 AdapterPtr adapterForAddress(const QString &address) const;
190
191 /*!
192 * Returns an adapter for specified UBI.
193 *
194 * \a ubi The UBI of adapter (eg. "/org/bluez/hci0")
195 */
196 AdapterPtr adapterForUbi(const QString &ubi) const;
197
198 /*!
199 * Returns a device for the specified address.
200 *
201 * \note There may be more devices with the same address (same device
202 * in multiple adapters). In this case, the first found device will
203 * be returned while preferring powered adapters in search.
204 *
205 * \a address The address of device (eg. "40:79:6A:0C:39:75")
206 */
207 DevicePtr deviceForAddress(const QString &address) const;
208
209 /*!
210 * Returns a device for specified UBI.
211 *
212 * \a ubi The UBI of device (eg. "/org/bluez/hci0/dev_40_79_6A_0C_39_75")
213 */
214 DevicePtr deviceForUbi(const QString &ubi) const;
215
216 /*!
217 * Registers an \a agent.
218 *
219 * This agent will be used for for all actions triggered by the application.
220 * Eg. show a PIN code in pairing process.
221 *
222 * Possible errors:
223 *
224 * \list
225 * \li PendingCall::InvalidArguments
226 * \li PendingCall::AlreadyExists
227 * \endlist
228 *
229 * Returns void pending call.
230 */
231 PendingCall *registerAgent(Agent *agent);
232
233 /*!
234 * Unregisters an \a agent.
235 *
236 * Possible errors:
237 *
238 * \list
239 * \li PendingCall::DoesNotExist
240 * \endlist
241 *
242 * Returns void pending call.
243 */
244 PendingCall *unregisterAgent(Agent *agent);
245
246 /*!
247 * Requests the default \a agent.
248 *
249 * This requests to make the application agent the default agent.
250 *
251 * Possible errors:
252 *
253 * \list
254 * \li PendingCall::DoesNotExist
255 * \endlist
256 *
257 * Returns void pending call.
258 */
259 PendingCall *requestDefaultAgent(Agent *agent);
260
261 /*!
262 * Registers a \a profile.
263 *
264 * Possible errors:
265 *
266 * \list
267 * \li PendingCall::InvalidArguments
268 * \li PendingCall::AlreadyExists
269 * \endlist
270 *
271 * Returns void pending call.
272 */
273 PendingCall *registerProfile(Profile *profile);
274
275 /*!
276 * Unregisters a \a profile.
277 *
278 * Possible errors:
279 *
280 * \list
281 * \li PendingCall::DoesNotExist
282 * \endlist
283 *
284 * Returns void pending call.
285 */
286 PendingCall *unregisterProfile(Profile *profile);
287
288 /*!
289 */
290 Rfkill *rfkill() const;
291
292Q_SIGNALS:
293 /*!
294 * Indicates that the \a operational state has changed.
295 */
296 void operationalChanged(bool operational);
297
298 /*!
299 * Indicates that the Bluetooth \a operational state has changed.
300 */
301 void bluetoothOperationalChanged(bool operational);
302
303 /*!
304 * Indicates that Bluetooth \a blocked state has changed.
305 */
306 void bluetoothBlockedChanged(bool blocked);
307
308 /*!
309 * Indicates that an \a adapter was added.
310 */
311 void adapterAdded(AdapterPtr adapter);
312
313 /*!
314 * Indicates that an \a adapter was removed.
315 */
316 void adapterRemoved(AdapterPtr adapter);
317
318 /*!
319 * Indicates that at least one of the \a adapter's properties has changed.
320 */
321 void adapterChanged(AdapterPtr adapter);
322
323 /*!
324 * Indicates that a new \a device was added (found by discovery).
325 */
326 void deviceAdded(DevicePtr device);
327
328 /*!
329 * Indicates that a \a device was removed.
330 */
331 void deviceRemoved(DevicePtr device);
332
333 /*!
334 * Indicates that at least one of the \a device's properties has changed.
335 */
336 void deviceChanged(DevicePtr device);
337
338 /*!
339 * Indicates that a usable \a adapter has changed.
340 */
341 void usableAdapterChanged(AdapterPtr adapter);
342
343 /*!
344 * Indicates that all adapters were removed.
345 */
346 void allAdaptersRemoved();
347
348private:
349 std::unique_ptr<class ManagerPrivate> const d;
350
351 friend class ManagerPrivate;
352 friend class InitManagerJobPrivate;
353};
354
355} // namespace BluezQt
356
357#endif // BLUEZQT_MANAGER_H
358

source code of bluez-qt/src/manager.h