1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_P_H
5#define QBLUETOOTHSERVICEDISCOVERYAGENT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qbluetoothaddress.h"
19#include "qbluetoothdeviceinfo.h"
20#include "qbluetoothserviceinfo.h"
21#include "qbluetoothservicediscoveryagent.h"
22
23#include <QStack>
24#include <QStringList>
25
26#if QT_CONFIG(bluez)
27
28namespace QtBluetoothPrivate {
29
30class OrgBluezManagerInterface;
31class OrgBluezAdapterInterface;
32class OrgBluezDeviceInterface;
33class OrgFreedesktopDBusObjectManagerInterface;
34
35} // namespace QtBluetoothPrivate
36
37#include <QtCore/qprocess.h>
38
39QT_BEGIN_NAMESPACE
40class QDBusPendingCallWatcher;
41class QXmlStreamReader;
42QT_END_NAMESPACE
43#endif
44
45#ifdef QT_WINRT_BLUETOOTH
46#include <QtCore/QPointer>
47#endif
48
49#ifdef QT_OSX_BLUETOOTH
50#include "darwin/btdelegates_p.h"
51#include "darwin/btraii_p.h"
52#endif
53
54#ifdef QT_ANDROID_BLUETOOTH
55#include <QtCore/QJniObject>
56#include <QtBluetooth/QBluetoothLocalDevice>
57#endif
58
59QT_BEGIN_NAMESPACE
60
61class QBluetoothDeviceDiscoveryAgent;
62#ifdef QT_ANDROID_BLUETOOTH
63class ServiceDiscoveryBroadcastReceiver;
64class LocalDeviceBroadcastReceiver;
65#endif
66
67#ifdef QT_WINRT_BLUETOOTH
68class QWinRTBluetoothServiceDiscoveryWorker;
69#endif
70
71class QBluetoothServiceDiscoveryAgentPrivate
72#if defined(QT_WINRT_BLUETOOTH)
73 : public QObject
74{
75 Q_OBJECT
76#elif defined(QT_OSX_BLUETOOTH)
77 : public QObject, public DarwinBluetooth::SDPInquiryDelegate
78{
79#else
80{
81#endif
82 Q_DECLARE_PUBLIC(QBluetoothServiceDiscoveryAgent)
83
84public:
85 enum DiscoveryState {
86 Inactive,
87 DeviceDiscovery,
88 ServiceDiscovery,
89 };
90
91 QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp,
92 const QBluetoothAddress &deviceAdapter);
93 ~QBluetoothServiceDiscoveryAgentPrivate();
94
95 void startDeviceDiscovery();
96 void stopDeviceDiscovery();
97 void startServiceDiscovery();
98 void stopServiceDiscovery();
99
100 void setDiscoveryState(DiscoveryState s) { state = s; }
101 inline DiscoveryState discoveryState() { return state; }
102
103 void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m) { mode = m; }
104 QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode() { return mode; }
105
106 void _q_deviceDiscoveryFinished();
107 void _q_deviceDiscovered(const QBluetoothDeviceInfo &info);
108 void _q_serviceDiscoveryFinished();
109 void _q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error);
110#if QT_CONFIG(bluez)
111 void _q_sdpScannerDone(int exitCode, QProcess::ExitStatus status);
112 void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
113 const QString &errorDescription,
114 const QStringList &xmlRecords);
115#endif
116#ifdef QT_ANDROID_BLUETOOTH
117 void _q_processFetchedUuids(const QBluetoothAddress &address, const QList<QBluetoothUuid> &uuids);
118
119 void populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice,
120 const QList<QBluetoothUuid> &uuids);
121 void _q_fetchUuidsTimeout();
122 void _q_hostModeStateChanged(QBluetoothLocalDevice::HostMode state);
123#endif
124
125private:
126 void start(const QBluetoothAddress &address);
127 void stop();
128 bool isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const;
129
130#if QT_CONFIG(bluez)
131 void startBluez5(const QBluetoothAddress &address);
132 void runExternalSdpScan(const QBluetoothAddress &remoteAddress,
133 const QBluetoothAddress &localAddress);
134 void sdpScannerDone(int exitCode, QProcess::ExitStatus exitStatus);
135 QVariant readAttributeValue(QXmlStreamReader &xml);
136 QBluetoothServiceInfo parseServiceXml(const QString& xml);
137 void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
138#endif
139
140public:
141 QBluetoothServiceDiscoveryAgent::Error error;
142 QString errorString;
143 QBluetoothAddress deviceAddress;
144 QList<QBluetoothServiceInfo> discoveredServices;
145 QList<QBluetoothDeviceInfo> discoveredDevices;
146 QBluetoothAddress m_deviceAdapterAddress;
147
148private:
149 DiscoveryState state;
150 QList<QBluetoothUuid> uuidFilter;
151
152 QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent = nullptr;
153
154 QBluetoothServiceDiscoveryAgent::DiscoveryMode mode;
155
156 bool singleDevice;
157#if QT_CONFIG(bluez)
158 QString foundHostAdapterPath;
159 QtBluetoothPrivate::OrgFreedesktopDBusObjectManagerInterface *manager = nullptr;
160 QProcess *sdpScannerProcess = nullptr;
161#endif
162
163#ifdef QT_ANDROID_BLUETOOTH
164 ServiceDiscoveryBroadcastReceiver *receiver = nullptr;
165 LocalDeviceBroadcastReceiver *localDeviceReceiver = nullptr;
166
167 QJniObject btAdapter;
168 // The sdpCache caches service discovery results while it is running, and is
169 // cleared once finished. The cache is used as we may (or may not) get more accurate
170 // results after the first result. This temporary caching allows to send the
171 // serviceDiscovered() signal once per service and with the most accurate information.
172 // Partial cache clearing may occur already during the scan if the second (more accurate)
173 // scan result is received.
174 QMap<QBluetoothAddress,QPair<QBluetoothDeviceInfo,QList<QBluetoothUuid> > > sdpCache;
175#endif
176
177#ifdef QT_WINRT_BLUETOOTH
178private slots:
179 void processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info);
180 void onScanFinished(quint64 deviceAddress);
181 void onError();
182
183private:
184 void releaseWorker();
185 QPointer<QWinRTBluetoothServiceDiscoveryWorker> worker;
186#endif
187
188#ifdef QT_OSX_BLUETOOTH
189 // SDPInquiryDelegate:
190 void SDPInquiryFinished(void *device) override;
191 void SDPInquiryError(void *device, IOReturn errorCode) override;
192
193 void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
194 //void serviceDiscoveryFinished();
195
196 bool serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const;
197
198 DarwinBluetooth::ScopedPointer serviceInquiry;
199#endif // QT_OSX_BLUETOOTH
200
201protected:
202 QBluetoothServiceDiscoveryAgent *q_ptr;
203};
204
205QT_END_NAMESPACE
206
207#endif
208

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