1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtBluetooth module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_P_H
42#define QBLUETOOTHDEVICEDISCOVERYAGENT_P_H
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists purely as an
49// implementation detail. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include "qbluetoothdevicediscoveryagent.h"
56#ifdef QT_ANDROID_BLUETOOTH
57#include <QtAndroidExtras/QAndroidJniObject>
58#include "android/devicediscoverybroadcastreceiver_p.h"
59#include <QtCore/QTimer>
60#endif
61
62#ifdef Q_OS_DARWIN
63#include "osx/btdelegates_p.h"
64#include "osx/btraii_p.h"
65#endif // Q_OS_DARWIN
66
67#include <QtCore/QVariantMap>
68
69#include <QtBluetooth/QBluetoothAddress>
70#include <QtBluetooth/QBluetoothLocalDevice>
71
72#if QT_CONFIG(bluez)
73#include "bluez/bluez5_helper_p.h"
74
75class OrgBluezManagerInterface;
76class OrgBluezAdapterInterface;
77class OrgFreedesktopDBusObjectManagerInterface;
78class OrgFreedesktopDBusPropertiesInterface;
79class OrgBluezAdapter1Interface;
80class OrgBluezDevice1Interface;
81
82QT_BEGIN_NAMESPACE
83class QDBusVariant;
84QT_END_NAMESPACE
85#endif
86
87#ifdef QT_WIN_BLUETOOTH
88QT_BEGIN_NAMESPACE
89class QThread;
90
91class ThreadWorkerDeviceDiscovery : public QObject
92{
93 Q_OBJECT
94signals:
95 void discoveryCompleted(const QVariant res);
96};
97
98QT_END_NAMESPACE
99
100#elif defined(QT_WINRT_BLUETOOTH)
101#include <QtCore/QPointer>
102#include <QtCore/QTimer>
103
104using ManufacturerData = QHash<quint16, QByteArray>;
105Q_DECLARE_METATYPE(ManufacturerData)
106#endif
107
108QT_BEGIN_NAMESPACE
109
110#ifdef QT_WINRT_BLUETOOTH
111class QWinRTBluetoothDeviceDiscoveryWorker;
112#endif
113
114class QBluetoothDeviceDiscoveryAgentPrivate
115#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_WIN_BLUETOOTH) \
116 || defined(Q_OS_DARWIN)
117 : public QObject
118#if defined(Q_OS_MACOS)
119 , public DarwinBluetooth::DeviceInquiryDelegate
120#endif // Q_OS_MACOS
121{
122 Q_OBJECT
123#else // BlueZ
124{
125#endif
126 Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent)
127public:
128 QBluetoothDeviceDiscoveryAgentPrivate(
129 const QBluetoothAddress &deviceAdapter,
130 QBluetoothDeviceDiscoveryAgent *parent);
131 ~QBluetoothDeviceDiscoveryAgentPrivate();
132
133 void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
134 void stop();
135 bool isActive() const;
136
137#if QT_CONFIG(bluez)
138 void _q_deviceFound(const QString &address, const QVariantMap &dict);
139 void _q_propertyChanged(const QString &name, const QDBusVariant &value);
140 void _q_InterfacesAdded(const QDBusObjectPath &object_path,
141 InterfaceList interfaces_and_properties);
142 void _q_discoveryFinished();
143 void _q_discoveryInterrupted(const QString &path);
144 void _q_PropertiesChanged(const QString &interface,
145 const QString &path,
146 const QVariantMap &changed_properties,
147 const QStringList &invalidated_properties);
148 void _q_extendedDeviceDiscoveryTimeout();
149#endif
150
151private:
152 QList<QBluetoothDeviceInfo> discoveredDevices;
153 QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType;
154
155 QBluetoothDeviceDiscoveryAgent::Error lastError;
156 QString errorString;
157
158#ifdef QT_ANDROID_BLUETOOTH
159private slots:
160 void processSdpDiscoveryFinished();
161 void processDiscoveredDevices(const QBluetoothDeviceInfo &info, bool isLeResult);
162 friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject);
163 void stopLowEnergyScan();
164
165private:
166 void startLowEnergyScan();
167
168 DeviceDiscoveryBroadcastReceiver *receiver;
169 QBluetoothAddress m_adapterAddress;
170 short m_active;
171 QAndroidJniObject adapter;
172 QAndroidJniObject leScanner;
173 QTimer *leScanTimeout;
174
175 bool pendingCancel, pendingStart;
176#elif QT_CONFIG(bluez)
177 QBluetoothAddress m_adapterAddress;
178 bool pendingCancel;
179 bool pendingStart;
180 OrgBluezManagerInterface *manager = nullptr;
181 OrgBluezAdapterInterface *adapter = nullptr;
182 OrgFreedesktopDBusObjectManagerInterface *managerBluez5 = nullptr;
183 OrgBluezAdapter1Interface *adapterBluez5 = nullptr;
184 QTimer *discoveryTimer = nullptr;
185 QList<OrgFreedesktopDBusPropertiesInterface *> propertyMonitors;
186
187 void deviceFoundBluez5(const QString &devicePath, const QVariantMap &properties);
188 void startBluez5(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
189
190 bool useExtendedDiscovery;
191 QTimer extendedDiscoveryTimer;
192 QMap<QString, QVariantMap> devicesProperties;
193#endif
194
195#ifdef QT_WIN_BLUETOOTH
196public:
197 static QString discoveredLeDeviceSystemPath(const QBluetoothAddress &deviceAddress);
198
199private:
200 void cancelDiscovery();
201 void restartDiscovery();
202 void finishDiscovery(QBluetoothDeviceDiscoveryAgent::Error errorCode, const QString &errorText);
203
204 void startLeDevicesDiscovery();
205 void completeLeDevicesDiscovery(const QVariant &res);
206 void startClassicDevicesDiscovery(Qt::HANDLE hSearch = nullptr);
207 void completeClassicDevicesDiscovery(const QVariant &res);
208
209 void processDiscoveredDevice(const QBluetoothDeviceInfo &foundDevice);
210
211 QBluetoothAddress adapterAddress;
212 bool pendingCancel;
213 bool pendingStart;
214 bool active;
215
216 QThread *threadLE = nullptr;
217 QThread *threadClassic = nullptr;
218 ThreadWorkerDeviceDiscovery *threadWorkerLE = nullptr;
219 ThreadWorkerDeviceDiscovery *threadWorkerClassic = nullptr;
220#endif
221
222#ifdef QT_WINRT_BLUETOOTH
223private slots:
224 void registerDevice(const QBluetoothDeviceInfo &info);
225 void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields,
226 qint16 rssi, ManufacturerData manufacturerData);
227 void onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e);
228 void onScanFinished();
229
230private:
231 void disconnectAndClearWorker();
232 QPointer<QWinRTBluetoothDeviceDiscoveryWorker> worker;
233 QTimer *leScanTimer;
234#endif
235
236#ifdef Q_OS_DARWIN
237
238 void startLE();
239
240#ifdef Q_OS_MACOS
241
242 void startClassic();
243
244 // Classic (IOBluetooth) inquiry delegate's methods:
245 void inquiryFinished() override;
246 void error(IOReturn error) override;
247 void classicDeviceFound(void *device) override;
248 // Classic (IOBluetooth) errors:
249 void setError(IOReturn error, const QString &text = QString());
250
251#endif // Q_OS_MACOS
252
253 // LE scan delegates (CoreBluetooth, all Darwin OSes):
254 void LEinquiryFinished();
255 void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
256 void LEnotSupported();
257
258 // LE errors:
259 void setError(QBluetoothDeviceDiscoveryAgent::Error,
260 const QString &text = QString());
261
262 // Both LE and Classic devices go there:
263 void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo);
264
265 enum AgentState {
266 NonActive,
267 ClassicScan, // macOS (IOBluetooth) only
268 LEScan
269 } agentState;
270
271 QBluetoothAddress adapterAddress;
272
273 bool startPending;
274 bool stopPending;
275
276#ifdef Q_OS_MACOS
277
278 DarwinBluetooth::ScopedPointer controller;
279 DarwinBluetooth::ScopedPointer inquiry;
280
281#endif // Q_OS_MACOS
282
283 DarwinBluetooth::ScopedPointer inquiryLE;
284
285#endif // Q_OS_DARWIN
286
287 int lowEnergySearchTimeout;
288 QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods;
289 QBluetoothDeviceDiscoveryAgent *q_ptr;
290};
291
292QT_END_NAMESPACE
293
294#endif
295

source code of qtconnectivity/src/bluetooth/qbluetoothdevicediscoveryagent_p.h