diff options
author | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-10-29 10:15:54 +0100 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-11-10 10:01:52 +0100 |
commit | e0dc61db4af89cce14ade3582ac92e4b713c7982 (patch) | |
tree | dbdeffaf2648da1532144367953ce0d72ff86d50 /src | |
parent | f1372ef9a1c4ad5bb7c7bbd94116ec1203fc4243 (diff) |
Bluetooth - device (LE) discovery for iOS
Add a QBluetoothDeviceDiscoveryAgent for iOS, implementation is based on
Core Bluetooth framework. Low Energy devices scan only.
- Ctor with address: set error as invalid bluetooth adapter error,
Core Bluetooth framework does not provide access to the local adapter's address.
- Adjust a test - we do not have access to the 'local device' information on iOS
(no address, no number of devices etc.) - skip the last test in tst_deviceDiscovery.
Change-Id: I49080d021c340016aebc548cc8ed758777c66397
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/bluetooth.pro | 19 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h | 4 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtledeviceinquiry.mm | 2 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtledeviceinquiry_p.h | 5 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtutility.mm | 45 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtutility_p.h | 110 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm | 387 |
7 files changed, 558 insertions, 14 deletions
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index 2868229d..1b065a2c 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -168,6 +168,25 @@ config_bluez:qtHaveModule(dbus) { SOURCES -= qbluetoothservicediscoveryagent.cpp SOURCES -= qbluetoothsocket.cpp SOURCES -= qbluetoothserver.cpp +} else:ios { + message("iOS is currently an unsupported Bluetooth platform, WIP.") + + DEFINES += QT_IOS_BLUETOOTH + LIBS += -framework Foundation -framework CoreBluetooth + + OBJECTIVE_SOURCES += \ + qbluetoothdevicediscoveryagent_ios.mm + + include(osx/osxbt.pri) + SOURCES += \ + qbluetoothdevicediscoveryagent_p.cpp \ + qbluetoothlocaldevice_p.cpp \ + qbluetoothserviceinfo_p.cpp \ + qbluetoothservicediscoveryagent_p.cpp \ + qbluetoothsocket_p.cpp \ + qbluetoothserver_p.cpp \ + qlowenergycontroller_p.cpp + SOURCES -= qbluetoothdevicediscoveryagent.cpp } else { message("Unsupported Bluetooth platform, will not build a working QtBluetooth library.") message("Either no Qt D-Bus found or no BlueZ headers.") diff --git a/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h b/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h index cb8a70d3..65b5e61f 100644 --- a/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h +++ b/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h @@ -41,7 +41,9 @@ #include <QtCore/qglobal.h> -#import <Foundation/Foundation.h> +// Foundation _MUST_ be included before 'wrapper' - +// SDK 10.9 is broken and requires this trick. +#include <Foundation/Foundation.h> #include "corebluetoothwrapper_p.h" diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm index 60e3224d..2f5ec0bb 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm @@ -48,6 +48,8 @@ #include <QtCore/qloggingcategory.h> #include <QtCore/qdebug.h> +// Foundation header is already included by this point +// (a workaround for a broken 10.9 SDK). #include "corebluetoothwrapper_p.h" QT_BEGIN_NAMESPACE diff --git a/src/bluetooth/osx/osxbtledeviceinquiry_p.h b/src/bluetooth/osx/osxbtledeviceinquiry_p.h index 16a757a6..20004d30 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry_p.h +++ b/src/bluetooth/osx/osxbtledeviceinquiry_p.h @@ -47,7 +47,10 @@ #include <QtCore/qglobal.h> #include <QtCore/qlist.h> -#import <Foundation/Foundation.h> +// The Foundation header must be included before +// corebluetoothwrapper_p.h - a workaround for a broken +// 10.9 SDK. +#include <Foundation/Foundation.h> @class QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry); diff --git a/src/bluetooth/osx/osxbtutility.mm b/src/bluetooth/osx/osxbtutility.mm index b6818ef6..74ee84e6 100644 --- a/src/bluetooth/osx/osxbtutility.mm +++ b/src/bluetooth/osx/osxbtutility.mm @@ -159,6 +159,51 @@ QString qt_error_string(IOReturn errorCode) #endif + +// Apple has: CBUUID, NSUUID, CFUUID, IOBluetoothSDPUUID +// and it's handy to have several converters: + +QBluetoothUuid qt_uuid(CBUUID *uuid) +{ + if (!uuid) + return QBluetoothUuid(); + + QT_BT_MAC_AUTORELEASEPOOL; + + if (uuid.data.length != 16) // TODO: warning? + return QBluetoothUuid(); + + quint128 qtUuidData = {}; + const quint8 *const source = static_cast<const quint8 *>(uuid.data.bytes); + std::copy(source, source + 16, qtUuidData.data); + + return QBluetoothUuid(qtUuidData); +} + +CFStrongReference<CFUUIDRef> cf_uuid(const QBluetoothUuid &qtUuid) +{ + const quint128 qtUuidData = qtUuid.toUInt128(); + const quint8 *const data = qtUuidData.data; + + CFUUIDBytes bytes = {data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], + data[8], data[9], data[10], data[11], + data[12], data[13], data[14], data[15]}; + + CFUUIDRef cfUuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, bytes); + return CFStrongReference<CFUUIDRef>(cfUuid, false);// false == already retained. +} + +ObjCStrongReference<CBUUID> cb_uuid(const QBluetoothUuid &qtUuid) +{ + CFStrongReference<CFUUIDRef> cfUuid(cf_uuid(qtUuid)); + if (!cfUuid) + return ObjCStrongReference<CBUUID>(); + + ObjCStrongReference<CBUUID> cbUuid([CBUUID UUIDWithCFUUID:cfUuid], true); //true == retain. + return cbUuid; +} + } QT_END_NAMESPACE diff --git a/src/bluetooth/osx/osxbtutility_p.h b/src/bluetooth/osx/osxbtutility_p.h index c2a48e5f..8c4083d9 100644 --- a/src/bluetooth/osx/osxbtutility_p.h +++ b/src/bluetooth/osx/osxbtutility_p.h @@ -47,19 +47,10 @@ #include <QtCore/qglobal.h> #include <Foundation/Foundation.h> +// Only after Foundation.h! +#include "corebluetoothwrapper_p.h" -#ifndef QT_IOS_BLUETOOTH - -#include <IOBluetooth/Bluetooth.h> -#include <IOKit/IOReturn.h> - -@class IOBluetoothSDPUUID; - -#else - -#include <CoreBluetooth/CoreBluetooth.h> - -#endif +@class CBUUID; QT_BEGIN_NAMESPACE @@ -179,6 +170,97 @@ private: T *m_ptr; }; +// The type 'T' is some XXXRef from CoreFoundation and co. +// In principle, we can do a trick removing a pointer from a type +// when template is instantiated, but it's quite a lot of ugly pp-tokens +// like OSXBluetooth::CFStrongReference<OSXBluetooth::remove_pointer<CFUUIDRref> > strongReference; +// so instead we use 'T' everywhere, not 'T *' as can expected +// from a smart pointer. +template<class T> +class CFStrongReference { +public: + CFStrongReference() + : m_ptr(Q_NULLPTR) + { + } + + CFStrongReference(T obj, bool retain) + : m_ptr(obj) + { + if (m_ptr && retain) + CFRetain(m_ptr); + } + + CFStrongReference(const CFStrongReference &rhs) + { + if ((m_ptr = rhs.m_ptr)) + CFRetain(m_ptr); + } + + CFStrongReference &operator = (const CFStrongReference &rhs) + { + // "Old-style" implementation: + if (this != &rhs && m_ptr != rhs.m_ptr) { + if (m_ptr) + CFRelease(m_ptr); + if ((m_ptr = rhs.m_ptr)) + CFRetain(m_ptr); + } + + return *this; + } + +#ifdef Q_COMPILER_RVALUE_REFS + CFStrongReference(CFStrongReference &&xval) + { + m_ptr = xval.m_ptr; + xval.m_ptr = Q_NULLPTR; + } + + CFStrongReference &operator = (CFStrongReference &&xval) + { + m_ptr = xval.m_ptr; + xval.m_ptr = Q_NULLPTR; + return *this; + } +#endif + + ~CFStrongReference() + { + if (m_ptr) + CFRelease(m_ptr); + } + + void reset(T newVal) + { + if (m_ptr != newVal) { + if (m_ptr) + CFRelease(m_ptr); + if ((m_ptr = newVal)) + CFRetain(m_ptr); + } + } + + operator T() const + { + return m_ptr; + } + + T data() const + { + return m_ptr; + } + + T take() + { + T p = m_ptr; + m_ptr = Q_NULLPTR; + return p; + } +private: + T m_ptr; +}; + QString qt_address(NSString *address); #ifndef QT_IOS_BLUETOOTH @@ -192,6 +274,10 @@ QString qt_error_string(IOReturn errorCode); #endif +QBluetoothUuid qt_uuid(CBUUID *uuid); +CFStrongReference<CFUUIDRef> cf_uuid(const QBluetoothUuid &qtUuid); +ObjCStrongReference<CBUUID> cb_uuid(const QBluetoothUuid &qtUuid); + } // namespace OSXBluetooth // Logging category for both OS X and iOS. diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm new file mode 100644 index 00000000..20304d99 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm @@ -0,0 +1,387 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdevicediscoveryagent.h" +#include "osx/osxbtledeviceinquiry_p.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothdeviceinfo.h" +#include "osx/osxbtutility_p.h" +#include "qbluetoothuuid.h" + +#include <QtCore/qloggingcategory.h> +#include <QtCore/qstring.h> +#include <QtCore/qdebug.h> +#include <QtCore/qlist.h> + +#include <CoreBluetooth/CoreBluetooth.h> + +QT_BEGIN_NAMESPACE + +using OSXBluetooth::ObjCScopedPointer; + +class QBluetoothDeviceDiscoveryAgentPrivate : public OSXBluetooth::LEDeviceInquiryDelegate +{ + friend class QBluetoothDeviceDiscoveryAgent; +public: + QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &address, + QBluetoothDeviceDiscoveryAgent *q); + virtual ~QBluetoothDeviceDiscoveryAgentPrivate(); + + bool isValid() const; + bool isActive() const; + + void start(); + void stop(); + +private: + // LEDeviceInquiryDelegate: + void LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::Error error) Q_DECL_OVERRIDE; + void LEnotSupported() Q_DECL_OVERRIDE; + void LEdeviceFound(CBPeripheral *peripheral, const QBluetoothUuid &deviceUuid, + NSDictionary *advertisementData, NSNumber *RSSI) Q_DECL_OVERRIDE; + void LEdeviceInquiryFinished() Q_DECL_OVERRIDE; + + void setError(QBluetoothDeviceDiscoveryAgent::Error, const QString &text = QString()); + + QBluetoothDeviceDiscoveryAgent *q_ptr; + + QBluetoothDeviceDiscoveryAgent::Error lastError; + QString errorString; + + QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType; + + typedef ObjCScopedPointer<LEDeviceInquiryObjC> LEDeviceInquiry; + LEDeviceInquiry inquiryLE; + + typedef QList<QBluetoothDeviceInfo> DevicesList; + DevicesList discoveredDevices; + + bool startPending; + bool stopPending; +}; + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter, + QBluetoothDeviceDiscoveryAgent *q) : + q_ptr(q), + lastError(QBluetoothDeviceDiscoveryAgent::NoError), + inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry), + startPending(false), + stopPending(false) +{ + Q_UNUSED(adapter); + + Q_ASSERT_X(q != Q_NULLPTR, "QBluetoothDeviceDiscoveryAgentPrivate()", + "invalid q_ptr (null)"); + + // OSXBTLEDeviceInquiry can be constructed even if LE is not supported - + // at this stage it's only a memory allocation of the object itself, + // if it fails - we have some memory-related problems. + LEDeviceInquiry newInquiryLE([[LEDeviceInquiryObjC alloc] initWithDelegate:this]); + if (!newInquiryLE) { + qCWarning(QT_BT_OSX) << "QBluetoothDeviceDiscoveryAgentPrivate() " + "failed to initialize a device inquiry object"; + return; + } + + inquiryLE.reset(newInquiryLE.take()); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isValid() const +{ + // isValid() - Qt does not use exceptions, but the ctor + // can fail to initialize some important data-members + // - this is what meant here by valid/invalid. + return inquiryLE; +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if (startPending) + return true; + if (stopPending) + return false; + + return [inquiryLE isActive]; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start() +{ + Q_ASSERT_X(isValid(), "start()", "called on invalid device discovery agent"); + Q_ASSERT_X(!isActive(), "start()", "called on active device discovery agent"); + Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, + "startLE()", "called with an invalid Bluetooth adapter"); + + if (stopPending) { + startPending = true; + return; + } + + discoveredDevices.clear(); + setError(QBluetoothDeviceDiscoveryAgent::NoError); + + if (![inquiryLE start]) { + // We can be here only if we have some kind of + // resource allocation error. + setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QObject::tr("device discovery agent, failed to start: " + "resource allocation error")); + emit q_ptr->error(lastError); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + Q_ASSERT_X(isValid(), "stop()", "called on invalid device discovery agent"); + Q_ASSERT_X(isActive(), "stop()", "called whithout active inquiry"); + Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, + "stop()", "called with invalid bluetooth adapter"); + + startPending = false; + stopPending = true; + + setError(QBluetoothDeviceDiscoveryAgent::NoError); + // Can be asynchronous (depending on a status update of CBCentralManager). + // The call itself is always 'success'. + [inquiryLE stop]; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + // At the moment the only error reported by osxbtledeviceinquiry + // can be 'powered off' error, it happens + // after the LE scan started (so we have LE support and this is + // a real PoweredOffError). + Q_ASSERT_X(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError, + "LEdeviceInquiryError", "unexpected error"); + + startPending = false; + stopPending = false; + setError(error); + emit q_ptr->error(lastError); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported() +{ + startPending = false; + stopPending = false; + setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError); + emit q_ptr->error(lastError); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceFound(CBPeripheral *peripheral, const QBluetoothUuid &deviceUuid, + NSDictionary *advertisementData, + NSNumber *RSSI) +{ + Q_ASSERT_X(peripheral, "LEdeviceFound", "invalid peripheral (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + QString name; + if (peripheral.name && peripheral.name.length) { + name = QString::fromNSString(peripheral.name); + } else { + NSString *const localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]; + if (localName && [localName length]) + name = QString::fromNSString(localName); + } + + // TODO: fix 'classOfDevice' (0 for now). + QBluetoothDeviceInfo newDeviceInfo(deviceUuid, name, 0); + if (RSSI) + newDeviceInfo.setRssi([RSSI shortValue]); + // CoreBluetooth scans only for LE devices. + newDeviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + + // Update, append or discard. + for (int i = 0, e = discoveredDevices.size(); i < e; ++i) { + if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) { + if (discoveredDevices[i] == newDeviceInfo) + return; + + discoveredDevices.replace(i, newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); + return; + } + } + + discoveredDevices.append(newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceInquiryFinished() +{ + Q_ASSERT_X(isValid(), "LEdeviceInquiryFinished", "invalid device discovery agent"); + + if (stopPending && !startPending) { + stopPending = false; + emit q_ptr->canceled(); + } else if (startPending) { + startPending = false; + stopPending = false; + start(); + } else { + emit q_ptr->finished(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, + const QString &text) +{ + lastError = error; + + if (text.length() > 0) { + errorString = text; + } else { + switch (lastError) { + case QBluetoothDeviceDiscoveryAgent::NoError: + errorString = QString(); + break; + case QBluetoothDeviceDiscoveryAgent::PoweredOffError: + errorString = QObject::tr("device discovery agent: adapter is powered off"); + break; + case QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError: + errorString = QObject::tr("device discovery agent: invalid bluetooth adapter"); + break; + case QBluetoothDeviceDiscoveryAgent::InputOutputError: + errorString = QObject::tr("device discovery agent: input output error"); + break; + case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError: + errorString = QObject::tr("Bluetooth LE is not supported"); + break; + case QBluetoothDeviceDiscoveryAgent::UnknownError: + default: + errorString = QObject::tr("device discovery agent: unknown error"); + } + } +} + +QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this)) +{ +} + +QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent( + const QBluetoothAddress &deviceAdapter, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this)) +{ + if (!deviceAdapter.isNull()) { + qCWarning(QT_BT_OSX) << "QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(), " + "local device address is not available, provided address is ignored"; + d_ptr->setError(InvalidBluetoothAdapterError); + } +} + +QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent() +{ + delete d_ptr; +} + +QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const +{ + return d_ptr->inquiryType; +} + +void QBluetoothDeviceDiscoveryAgent::setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type) +{ + d_ptr->inquiryType = type; +} + +QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const +{ + return d_ptr->discoveredDevices; +} + +void QBluetoothDeviceDiscoveryAgent::start() +{ + if (d_ptr->lastError != InvalidBluetoothAdapterError) { + if (d_ptr->isValid()) { + if (!isActive()) { + d_ptr->start(); + } else { + qCDebug(QT_BT_OSX) << "QBluetoothDeviceDiscoveryAgent::start(), " + "already started"; + } + } else { + // We previously failed to initialize + // private object correctly. + d_ptr->setError(InvalidBluetoothAdapterError); + emit error(InvalidBluetoothAdapterError); + } + } +} + +void QBluetoothDeviceDiscoveryAgent::stop() +{ + if (d_ptr->isValid()) { + if (isActive() && d_ptr->lastError != InvalidBluetoothAdapterError) { + d_ptr->stop(); + } else { + qCDebug(QT_BT_OSX) << "QBluetoothDeviceDiscoveryAgent::stop(), " + "failed to stop"; + } + } +} + +bool QBluetoothDeviceDiscoveryAgent::isActive() const +{ + if (d_ptr->isValid()) + return d_ptr->isActive(); + + return false; +} + +QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const +{ + return d_ptr->lastError; +} + +QString QBluetoothDeviceDiscoveryAgent::errorString() const +{ + return d_ptr->errorString; +} + +QT_END_NAMESPACE |