11#include <QtCore/QFile>
12#include <QtCore/QLibraryInfo>
13#include <QtCore/QLoggingCategory>
14#include <QtCore/QProcess>
15#include <QtCore/QScopeGuard>
17#include <QtDBus/QDBusPendingCallWatcher>
32 qRegisterMetaType<QBluetoothServiceDiscoveryAgent::Error>();
46 if (foundHostAdapterPath.isEmpty()) {
54 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Cannot access adapter during service discovery");
60 if (foundHostAdapterPath.isEmpty()) {
66 errorString = QBluetoothServiceDiscoveryAgent::tr(
"Cannot find local Bluetooth adapter");
77 if (!adapter.powered()) {
81 errorString = QBluetoothServiceDiscoveryAgent::tr(
"Local device is powered off");
89 performMinimalServiceDiscovery(
address);
99void QBluetoothServiceDiscoveryAgentPrivate::runExternalSdpScan(
104 if (!sdpScannerProcess) {
107 if (!fileInfo.exists() || !fileInfo.isExecutable()) {
109 QBluetoothServiceDiscoveryAgent::tr(
"Unable to find sdpscanner"),
111 qCWarning(QT_BT_BLUEZ) <<
"Cannot find sdpscanner:"
112 << fileInfo.canonicalFilePath();
116 sdpScannerProcess =
new QProcess(
q);
117 sdpScannerProcess->setReadChannel(QProcess::StandardOutput);
118 if (QT_BT_BLUEZ().isDebugEnabled())
119 sdpScannerProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel);
120 sdpScannerProcess->setProgram(fileInfo.canonicalFilePath());
121 q->connect(sdpScannerProcess,
123 q, [
this](
int exitCode, QProcess::ExitStatus status){
124 this->_q_sdpScannerDone(exitCode, status);
129 arguments << remoteAddress.toString() << localAddress.toString();
138 sdpScannerProcess->setArguments(
arguments);
139 sdpScannerProcess->start();
142void QBluetoothServiceDiscoveryAgentPrivate::_q_sdpScannerDone(
int exitCode, QProcess::ExitStatus status)
144 if (status != QProcess::NormalExit || exitCode != 0) {
145 qCWarning(QT_BT_BLUEZ) <<
"SDP scan failure" << status << exitCode;
148 QBluetoothServiceDiscoveryAgent::tr(
"Unable to perform SDP scan"),
173 }
while (
start != -1);
180 const QString &errorDescription,
186 qCWarning(QT_BT_BLUEZ) <<
"SDP search failed for"
201 bool serviceNameMatched = uuidFilter.
contains(serviceInfo.serviceUuid());
202 bool serviceClassMatched =
false;
203 const QList<QBluetoothUuid> serviceClassUuids
204 = serviceInfo.serviceClassUuids();
207 serviceClassMatched =
true;
212 if (!serviceNameMatched && !serviceClassMatched)
216 if (!serviceInfo.isValid())
222 const QList<QBluetoothUuid> serviceClassUuids = serviceInfo.serviceClassUuids();
224 if (
id.minimumSize() == 16) {
225 serviceInfo.setServiceUuid(
id);
226 if (serviceInfo.serviceName().isEmpty()) {
227 serviceInfo.setServiceName(
228 QBluetoothServiceDiscoveryAgent::tr(
"Custom Service"));
238 if (!isDuplicatedService(serviceInfo)) {
241 << serviceInfo.serviceName() << serviceInfo.serviceUuid()
242 <<
">>>" << serviceInfo.serviceClassUuids();
254void QBluetoothServiceDiscoveryAgentPrivate::stop()
263 if (sdpScannerProcess) {
264 if (sdpScannerProcess->state() != QProcess::NotRunning) {
265 sdpScannerProcess->kill();
266 sdpScannerProcess->waitForFinished();
277 QXmlStreamReader
xml(xmlRecord);
282 while (!
xml.atEnd()) {
285 if (
xml.tokenType() == QXmlStreamReader::StartElement &&
290 if (
xml.readNextStartElement()) {
292 serviceInfo.setAttribute(attributeId,
value);
301void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(
const QBluetoothAddress &deviceAddress)
303 if (foundHostAdapterPath.isEmpty()) {
310 QDBusPendingReply<ManagedObjectList>
reply =
manager->GetManagedObjects();
311 reply.waitForFinished();
312 if (
reply.isError()) {
325 for (ManagedObjectList::const_iterator
it = managedObjectList.
constBegin();
it != managedObjectList.
constEnd(); ++
it) {
339 if (!uuidStrings.isEmpty())
366 serviceInfo.setServiceUuid(uuid);
367 serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr(
"Custom Service"));
392 if (!isDuplicatedService(serviceInfo)) {
395 << serviceInfo.serviceName();
396 emit q->serviceDiscovered(serviceInfo);
403QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamReader &
xml)
405 auto skippingCurrentElementByDefault =
qScopeGuard([&] {
xml.skipCurrentElement(); });
425 if (
value.size() == 6) {
428 }
else if (
value.size() == 10) {
440 return value.toString();
444 skippingCurrentElementByDefault.dismiss();
446 while (
xml.readNextStartElement()) {
451 return QVariant::fromValue<QBluetoothServiceInfo::Sequence>(sequence);
453 qCWarning(QT_BT_BLUEZ) <<
"unknown attribute type"
QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok=nullptr)
QMap< QDBusObjectPath, InterfaceList > ManagedObjectList
QT_BEGIN_NAMESPACE void initializeBluez5()
QBluetoothAddress address() const
Returns the address of the device.
QBluetoothAddress deviceAddress
void setDiscoveryState(DiscoveryState s)
~QBluetoothServiceDiscoveryAgentPrivate()
QList< QBluetoothServiceInfo > discoveredServices
void _q_serviceDiscoveryFinished()
QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter)
DiscoveryState discoveryState()
QList< QBluetoothDeviceInfo > discoveredDevices
QBluetoothServiceDiscoveryAgent::Error error
QBluetoothAddress m_deviceAdapterAddress
QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode()
Error
This enum describes errors that can occur during service discovery.
@ InvalidBluetoothAdapterError
void setDevice(const QBluetoothDeviceInfo &info)
Sets the Bluetooth device that provides this service to device.
int minimumSize() const
Returns the minimum size in bytes that this UUID can be represented in.
ServiceClassUuid
This enum is a convienience type for Bluetooth service class and profile UUIDs.
static QString serviceClassToString(ServiceClassUuid uuid)
Returns a human-readable and translated name for the given service class represented by uuid.
static QByteArray fromHex(const QByteArray &hexEncoded)
Returns a decoded copy of the hex encoded array hexEncoded.
static QByteArray fromBase64(const QByteArray &base64, Base64Options options=Base64Encoding)
static QDBusConnection systemBus()
Returns a QDBusConnection object opened with the system bus.
static QString path(LibraryPath p)
bool isEmpty() const noexcept
bool removeOne(const AT &t)
const_reference at(qsizetype i) const noexcept
T value(qsizetype i) const
void append(parameter_type t)
T value(const Key &key, const T &defaultValue=T()) const
NetworkError error() const
Returns the error that was found during the processing of this request.
const_iterator constBegin() const noexcept
const_iterator constEnd() const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QSet< QString >::iterator it
QList< QVariant > arguments
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
constexpr QStaticByteArrayMatcher< N > qMakeStaticByteArrayMatcher(const char(&pattern)[N]) noexcept
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define Q_ARG(Type, data)
GLsizei const GLfloat * v
[13]
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static QStringList toStringList(const QJsonArray &jsonArray)
unsigned long long quint64
static const auto matcher
[0]
QNetworkAccessManager manager
char * toString(const MyType &t)
[31]
bool contains(const AT &t) const noexcept