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 QBLUETOOTHSERVICEDISCOVERYAGENT_P_H
41#define QBLUETOOTHSERVICEDISCOVERYAGENT_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 "qbluetoothaddress.h"
55#include "qbluetoothdeviceinfo.h"
56#include "qbluetoothserviceinfo.h"
57#include "qbluetoothservicediscoveryagent.h"
58
59#include <QStack>
60#include <QStringList>
61
62#if QT_CONFIG(bluez)
63class OrgBluezManagerInterface;
64class OrgBluezAdapterInterface;
65class OrgBluezDeviceInterface;
66class OrgFreedesktopDBusObjectManagerInterface;
67#include <QtCore/qprocess.h>
68
69QT_BEGIN_NAMESPACE
70class QDBusPendingCallWatcher;
71class QXmlStreamReader;
72QT_END_NAMESPACE
73#endif
74
75#ifdef QT_WINRT_BLUETOOTH
76#include <QtCore/QPointer>
77#endif
78
79#ifdef QT_OSX_BLUETOOTH
80#include "osx/btdelegates_p.h"
81#include "osx/btraii_p.h"
82#endif
83
84QT_BEGIN_NAMESPACE
85
86class QBluetoothDeviceDiscoveryAgent;
87#ifdef QT_ANDROID_BLUETOOTH
88class ServiceDiscoveryBroadcastReceiver;
89class LocalDeviceBroadcastReceiver;
90#include <QtAndroidExtras/QAndroidJniObject>
91#include <QtBluetooth/QBluetoothLocalDevice>
92#endif
93
94#ifdef QT_WINRT_BLUETOOTH
95class QWinRTBluetoothServiceDiscoveryWorker;
96#endif
97
98class QBluetoothServiceDiscoveryAgentPrivate
99#if defined QT_WINRT_BLUETOOTH
100 : public QObject
101{
102 Q_OBJECT
103#elif defined(QT_OSX_BLUETOOTH)
104 : public QObject, public DarwinBluetooth::SDPInquiryDelegate
105{
106#else
107{
108#endif
109 Q_DECLARE_PUBLIC(QBluetoothServiceDiscoveryAgent)
110
111public:
112 enum DiscoveryState {
113 Inactive,
114 DeviceDiscovery,
115 ServiceDiscovery,
116 };
117
118 QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp,
119 const QBluetoothAddress &deviceAdapter);
120 ~QBluetoothServiceDiscoveryAgentPrivate();
121
122 void startDeviceDiscovery();
123 void stopDeviceDiscovery();
124 void startServiceDiscovery();
125 void stopServiceDiscovery();
126
127 void setDiscoveryState(DiscoveryState s) { state = s; }
128 inline DiscoveryState discoveryState() { return state; }
129
130 void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m) { mode = m; }
131 QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode() { return mode; }
132
133 void _q_deviceDiscoveryFinished();
134 void _q_deviceDiscovered(const QBluetoothDeviceInfo &info);
135 void _q_serviceDiscoveryFinished();
136 void _q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error);
137#if QT_CONFIG(bluez)
138 void _q_discoveredServices(QDBusPendingCallWatcher *watcher);
139 void _q_createdDevice(QDBusPendingCallWatcher *watcher);
140 void _q_foundDevice(QDBusPendingCallWatcher *watcher);
141 //Slots below are used for discovering Bluetooth Low Energy devices. It will be used with Bluez 5.x version.
142 /*
143 void _g_discoveredGattService();
144 void _q_discoverGattCharacteristics(QDBusPendingCallWatcher *watcher);
145 void _q_discoveredGattCharacteristic(QDBusPendingCallWatcher *watcher);
146 */
147 void _q_sdpScannerDone(int exitCode, QProcess::ExitStatus status);
148 void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
149 const QString &errorDescription,
150 const QStringList &xmlRecords);
151#endif
152#ifdef QT_ANDROID_BLUETOOTH
153 void _q_processFetchedUuids(const QBluetoothAddress &address, const QList<QBluetoothUuid> &uuids);
154
155 void populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice,
156 const QList<QBluetoothUuid> &uuids);
157 void _q_fetchUuidsTimeout();
158 void _q_hostModeStateChanged(QBluetoothLocalDevice::HostMode state);
159#endif
160
161private:
162 void start(const QBluetoothAddress &address);
163 void stop();
164 bool isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const;
165
166#if QT_CONFIG(bluez)
167 void startBluez5(const QBluetoothAddress &address);
168 void runExternalSdpScan(const QBluetoothAddress &remoteAddress,
169 const QBluetoothAddress &localAddress);
170 void sdpScannerDone(int exitCode, QProcess::ExitStatus exitStatus);
171 QVariant readAttributeValue(QXmlStreamReader &xml);
172 QBluetoothServiceInfo parseServiceXml(const QString& xml);
173 void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
174 void discoverServices(const QString &deviceObjectPath);
175#endif
176
177public:
178 QBluetoothServiceDiscoveryAgent::Error error;
179 QString errorString;
180 QBluetoothAddress deviceAddress;
181 QList<QBluetoothServiceInfo> discoveredServices;
182 QList<QBluetoothDeviceInfo> discoveredDevices;
183 QBluetoothAddress m_deviceAdapterAddress;
184
185private:
186 DiscoveryState state;
187 QList<QBluetoothUuid> uuidFilter;
188
189 QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent = nullptr;
190
191 QBluetoothServiceDiscoveryAgent::DiscoveryMode mode;
192
193 bool singleDevice;
194#if QT_CONFIG(bluez)
195 QString foundHostAdapterPath;
196 OrgBluezManagerInterface *manager = nullptr;
197 OrgFreedesktopDBusObjectManagerInterface *managerBluez5 = nullptr;
198 OrgBluezAdapterInterface *adapter = nullptr;
199 OrgBluezDeviceInterface *device = nullptr;
200 QProcess *sdpScannerProcess = nullptr;
201#endif
202
203#ifdef QT_ANDROID_BLUETOOTH
204 ServiceDiscoveryBroadcastReceiver *receiver = nullptr;
205 LocalDeviceBroadcastReceiver *localDeviceReceiver = nullptr;
206
207 QAndroidJniObject btAdapter;
208 QMap<QBluetoothAddress,QPair<QBluetoothDeviceInfo,QList<QBluetoothUuid> > > sdpCache;
209#endif
210
211#ifdef QT_WINRT_BLUETOOTH
212private slots:
213 void processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info);
214 void onScanFinished(quint64 deviceAddress);
215 void onScanCanceled();
216 void onError();
217
218private:
219 QPointer<QWinRTBluetoothServiceDiscoveryWorker> worker;
220#endif
221
222#ifdef QT_OSX_BLUETOOTH
223 // SDPInquiryDelegate:
224 void SDPInquiryFinished(void *device) override;
225 void SDPInquiryError(void *device, IOReturn errorCode) override;
226
227 void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
228 //void serviceDiscoveryFinished();
229
230 bool serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const;
231
232 DarwinBluetooth::ScopedPointer serviceInquiry;
233#endif // QT_OSX_BLUETOOTH
234
235protected:
236 QBluetoothServiceDiscoveryAgent *q_ptr;
237};
238
239QT_END_NAMESPACE
240
241#endif
242