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