1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com> |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_P_H |
6 | #define QBLUETOOTHDEVICEDISCOVERYAGENT_P_H |
7 | |
8 | // |
9 | // W A R N I N G |
10 | // ------------- |
11 | // |
12 | // This file is not part of the Qt API. It exists purely as an |
13 | // implementation detail. This header file may change from version to |
14 | // version without notice, or even be removed. |
15 | // |
16 | // We mean it. |
17 | // |
18 | |
19 | #include "qbluetoothdevicediscoveryagent.h" |
20 | #ifdef QT_ANDROID_BLUETOOTH |
21 | #include <QtCore/QJniObject> |
22 | #include "android/devicediscoverybroadcastreceiver_p.h" |
23 | #include <QtCore/QTimer> |
24 | #endif |
25 | |
26 | #ifdef Q_OS_DARWIN |
27 | #include "darwin/btdelegates_p.h" |
28 | #include "darwin/btraii_p.h" |
29 | #endif // Q_OS_DARWIN |
30 | |
31 | #include <QtCore/QVariantMap> |
32 | |
33 | #include <QtBluetooth/QBluetoothAddress> |
34 | #include <QtBluetooth/QBluetoothLocalDevice> |
35 | |
36 | #if QT_CONFIG(bluez) |
37 | #include "bluez/bluez5_helper_p.h" |
38 | |
39 | class OrgBluezManagerInterface; |
40 | class OrgBluezAdapterInterface; |
41 | class OrgFreedesktopDBusObjectManagerInterface; |
42 | class OrgFreedesktopDBusPropertiesInterface; |
43 | class OrgBluezAdapter1Interface; |
44 | class OrgBluezDevice1Interface; |
45 | |
46 | QT_BEGIN_NAMESPACE |
47 | class QDBusVariant; |
48 | QT_END_NAMESPACE |
49 | #endif |
50 | |
51 | #ifdef QT_WINRT_BLUETOOTH |
52 | #include <QtCore/QPointer> |
53 | #include <QtCore/QTimer> |
54 | |
55 | using ManufacturerData = QHash<quint16, QByteArray>; |
56 | using ServiceData = QHash<QBluetoothUuid, QByteArray>; |
57 | QT_DECL_METATYPE_EXTERN(ManufacturerData, Q_BLUETOOTH_EXPORT) |
58 | QT_DECL_METATYPE_EXTERN(ServiceData, Q_BLUETOOTH_EXPORT) |
59 | #endif |
60 | |
61 | QT_BEGIN_NAMESPACE |
62 | |
63 | #ifdef QT_WINRT_BLUETOOTH |
64 | class QWinRTBluetoothDeviceDiscoveryWorker; |
65 | #endif |
66 | |
67 | class QBluetoothDeviceDiscoveryAgentPrivate |
68 | #if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) \ |
69 | || defined(Q_OS_DARWIN) |
70 | : public QObject |
71 | #if defined(Q_OS_MACOS) |
72 | , public DarwinBluetooth::DeviceInquiryDelegate |
73 | #endif // Q_OS_MACOS |
74 | { |
75 | Q_OBJECT |
76 | #else // BlueZ |
77 | { |
78 | #endif |
79 | Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent) |
80 | public: |
81 | QBluetoothDeviceDiscoveryAgentPrivate( |
82 | const QBluetoothAddress &deviceAdapter, |
83 | QBluetoothDeviceDiscoveryAgent *parent); |
84 | ~QBluetoothDeviceDiscoveryAgentPrivate(); |
85 | |
86 | void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods); |
87 | void stop(); |
88 | bool isActive() const; |
89 | |
90 | #if QT_CONFIG(bluez) |
91 | void _q_InterfacesAdded(const QDBusObjectPath &object_path, |
92 | InterfaceList interfaces_and_properties); |
93 | void _q_discoveryFinished(); |
94 | void _q_discoveryInterrupted(const QString &path); |
95 | void _q_PropertiesChanged(const QString &interface, |
96 | const QString &path, |
97 | const QVariantMap &changed_properties, |
98 | const QStringList &invalidated_properties); |
99 | #endif |
100 | |
101 | private: |
102 | QList<QBluetoothDeviceInfo> discoveredDevices; |
103 | |
104 | QBluetoothDeviceDiscoveryAgent::Error lastError = QBluetoothDeviceDiscoveryAgent::NoError; |
105 | QString errorString; |
106 | QBluetoothAddress adapterAddress; |
107 | |
108 | #ifdef QT_ANDROID_BLUETOOTH |
109 | private slots: |
110 | void processSdpDiscoveryFinished(); |
111 | void processDiscoveredDevices(const QBluetoothDeviceInfo &info, bool isLeResult); |
112 | friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject); |
113 | void stopLowEnergyScan(); |
114 | |
115 | private: |
116 | void startLowEnergyScan(); |
117 | void classicDiscoveryStartFail(); |
118 | bool setErrorIfPowerOff(); |
119 | |
120 | DeviceDiscoveryBroadcastReceiver *receiver = nullptr; |
121 | short m_active; |
122 | QJniObject adapter; |
123 | QJniObject leScanner; |
124 | QTimer *leScanTimeout = nullptr; |
125 | QTimer *deviceDiscoveryStartTimeout = nullptr; |
126 | short deviceDiscoveryStartAttemptsLeft; |
127 | |
128 | bool pendingCancel = false; |
129 | bool pendingStart = false; |
130 | #elif QT_CONFIG(bluez) |
131 | bool pendingCancel = false; |
132 | bool pendingStart = false; |
133 | OrgFreedesktopDBusObjectManagerInterface *manager = nullptr; |
134 | OrgBluezAdapter1Interface *adapter = nullptr; |
135 | QTimer *discoveryTimer = nullptr; |
136 | QList<OrgFreedesktopDBusPropertiesInterface *> propertyMonitors; |
137 | |
138 | void deviceFound(const QString &devicePath, const QVariantMap &properties); |
139 | |
140 | QMap<QString, QVariantMap> devicesProperties; |
141 | #endif |
142 | |
143 | #ifdef QT_WINRT_BLUETOOTH |
144 | private slots: |
145 | void registerDevice(const QBluetoothDeviceInfo &info); |
146 | void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields, |
147 | qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData); |
148 | void onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e); |
149 | void onScanFinished(); |
150 | |
151 | private: |
152 | void disconnectAndClearWorker(); |
153 | std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker = nullptr; |
154 | #endif |
155 | |
156 | #ifdef Q_OS_DARWIN |
157 | |
158 | void startLE(); |
159 | |
160 | #ifdef Q_OS_MACOS |
161 | |
162 | void startClassic(); |
163 | |
164 | // Classic (IOBluetooth) inquiry delegate's methods: |
165 | void inquiryFinished() override; |
166 | void error(IOReturn error) override; |
167 | void classicDeviceFound(void *device) override; |
168 | // Classic (IOBluetooth) errors: |
169 | void setError(IOReturn error, const QString &text = QString()); |
170 | |
171 | #endif // Q_OS_MACOS |
172 | |
173 | // LE scan delegates (CoreBluetooth, all Darwin OSes): |
174 | void LEinquiryFinished(); |
175 | void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error); |
176 | void LEnotSupported(); |
177 | |
178 | // LE errors: |
179 | void setError(QBluetoothDeviceDiscoveryAgent::Error, |
180 | const QString &text = QString()); |
181 | |
182 | // Both LE and Classic devices go there: |
183 | void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo); |
184 | |
185 | enum AgentState { |
186 | NonActive, |
187 | ClassicScan, // macOS (IOBluetooth) only |
188 | LEScan |
189 | } agentState; |
190 | |
191 | bool startPending = false; |
192 | bool stopPending = false; |
193 | |
194 | #ifdef Q_OS_MACOS |
195 | |
196 | DarwinBluetooth::ScopedPointer controller; |
197 | DarwinBluetooth::ScopedPointer inquiry; |
198 | |
199 | #endif // Q_OS_MACOS |
200 | |
201 | DarwinBluetooth::ScopedPointer inquiryLE; |
202 | |
203 | #endif // Q_OS_DARWIN |
204 | |
205 | int lowEnergySearchTimeout = 40000; |
206 | QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods; |
207 | QBluetoothDeviceDiscoveryAgent *q_ptr; |
208 | }; |
209 | |
210 | QT_END_NAMESPACE |
211 | |
212 | #endif |
213 | |