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 | |
20 | namespace BluezQt |
21 | { |
22 | class Device; |
23 | class Adapter; |
24 | class Agent; |
25 | class Profile; |
26 | class PendingCall; |
27 | class 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 | */ |
80 | class 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 | |
101 | public: |
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 | |
292 | Q_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 | |
348 | private: |
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 | |