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