diff options
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm | 352 |
1 files changed, 195 insertions, 157 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm index 1cfe8286..b308f7cc 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm @@ -1,79 +1,102 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company 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 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "qbluetoothdevicediscoverytimer_osx_p.h" #include "qbluetoothdevicediscoveryagent.h" #include "osx/osxbtledeviceinquiry_p.h" #include "osx/osxbtdeviceinquiry_p.h" #include "qbluetoothlocaldevice.h" #include "osx/osxbtsdpinquiry_p.h" #include "qbluetoothdeviceinfo.h" +#include "osx/osxbtnotifier_p.h" #include "osx/osxbtutility_p.h" +#include "osx/osxbluetooth_p.h" #include "osx/uistrings_p.h" #include "qbluetoothhostinfo.h" +#include "qbluetoothaddress.h" +#include "osx/uistrings_p.h" #include "qbluetoothuuid.h" #include <QtCore/qloggingcategory.h> #include <QtCore/qscopedpointer.h> -#include <QtCore/qdatetime.h> #include <QtCore/qglobal.h> #include <QtCore/qstring.h> #include <QtCore/qdebug.h> #include <QtCore/qlist.h> #include <Foundation/Foundation.h> -// Only after Foundation.h: -#include "osx/corebluetoothwrapper_p.h" QT_BEGIN_NAMESPACE -using OSXBluetooth::ObjCScopedPointer; +namespace +{ + +void registerQDeviceDiscoveryMetaType() +{ + static bool initDone = false; + if (!initDone) { + qRegisterMetaType<QBluetoothDeviceInfo>(); + qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>(); + initDone = true; + } +} + +}//namespace -class QBluetoothDeviceDiscoveryAgentPrivate : public OSXBluetooth::DeviceInquiryDelegate +class QBluetoothDeviceDiscoveryAgentPrivate : public QObject, + public OSXBluetooth::DeviceInquiryDelegate { friend class QBluetoothDeviceDiscoveryAgent; - friend class OSXBluetooth::DDATimerHandler; public: - typedef QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) LEDeviceInquiryObjC; + template<class T> + using ObjCScopedPointer = OSXBluetooth::ObjCScopedPointer<T>; + using LEDeviceInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry); QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress & address, QBluetoothDeviceDiscoveryAgent *q); - virtual ~QBluetoothDeviceDiscoveryAgentPrivate(); + + ~QBluetoothDeviceDiscoveryAgentPrivate() Q_DECL_OVERRIDE; bool isValid() const; bool isActive() const; - void start(); + void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods); + void startClassic(); void startLE(); void stop(); @@ -89,7 +112,6 @@ private: void error(IOBluetoothDeviceInquiry *inq, IOReturn error) Q_DECL_OVERRIDE; void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) Q_DECL_OVERRIDE; - // void LEinquiryFinished(); void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error); void LEnotSupported(); @@ -99,9 +121,8 @@ private: void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo); void setError(IOReturn error, const QString &text = QString()); - void setError(QBluetoothDeviceDiscoveryAgent::Error, const QString &text = QString()); - - void checkLETimeout(); + void setError(QBluetoothDeviceDiscoveryAgent::Error, + const QString &text = QString()); QBluetoothDeviceDiscoveryAgent *q_ptr; AgentState agentState; @@ -116,56 +137,22 @@ private: QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType; - typedef ObjCScopedPointer<DeviceInquiryObjC> DeviceInquiry; + using DeviceInquiry = ObjCScopedPointer<DeviceInquiryObjC>; DeviceInquiry inquiry; - typedef ObjCScopedPointer<LEDeviceInquiryObjC> LEDeviceInquiry; + using LEDeviceInquiry = ObjCScopedPointer<LEDeviceInquiryObjC>; LEDeviceInquiry inquiryLE; - typedef ObjCScopedPointer<IOBluetoothHostController> HostController; + using HostController = ObjCScopedPointer<IOBluetoothHostController>; HostController hostController; - typedef QList<QBluetoothDeviceInfo> DevicesList; + using DevicesList = QList<QBluetoothDeviceInfo>; DevicesList discoveredDevices; - QScopedPointer<OSXBluetooth::DDATimerHandler> timer; + int lowEnergySearchTimeout; + QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods; }; -namespace OSXBluetooth { - -DDATimerHandler::DDATimerHandler(QBluetoothDeviceDiscoveryAgentPrivate *d) - : owner(d) -{ - Q_ASSERT_X(owner, Q_FUNC_INFO, "invalid pointer"); - - timer.setSingleShot(false); - connect(&timer, &QTimer::timeout, this, &DDATimerHandler::onTimer); -} - -void DDATimerHandler::start(int msec) -{ - Q_ASSERT_X(msec > 0, Q_FUNC_INFO, "invalid time interval"); - if (timer.isActive()) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "timer is active"; - return; - } - - timer.start(msec); -} - -void DDATimerHandler::stop() -{ - timer.stop(); -} - -void DDATimerHandler::onTimer() -{ - Q_ASSERT(owner); - owner->checkLETimeout(); -} - -} - QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter, QBluetoothDeviceDiscoveryAgent *q) : q_ptr(q), @@ -174,26 +161,22 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(con startPending(false), stopPending(false), lastError(QBluetoothDeviceDiscoveryAgent::NoError), - inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry) + inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry), + lowEnergySearchTimeout(OSXBluetooth::defaultLEScanTimeoutMS), + requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod + | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + registerQDeviceDiscoveryMetaType(); + Q_ASSERT_X(q != Q_NULLPTR, Q_FUNC_INFO, "invalid q_ptr (null)"); HostController controller([[IOBluetoothHostController defaultController] retain]); if (!controller || [controller powerState] != kBluetoothHCIPowerStateON) { - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "no default host " - "controller or adapter is off"; - return; - } - - DeviceInquiry newInquiry([[DeviceInquiryObjC alloc]initWithDelegate:this]); - if (!newInquiry) { // Obj-C's way of "reporting errors": - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "failed to " - "initialize an inquiry"; + qCCritical(QT_BT_OSX) << "no default host controller or adapter is off"; return; } hostController.reset(controller.take()); - inquiry.reset(newInquiry.take()); } QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() @@ -203,7 +186,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) { // Local variable to be retained ... LEDeviceInquiryObjC *inq = inquiryLE.data(); - dispatch_async(leQueue, ^{ + dispatch_sync(leQueue, ^{ [inq stop]; }); } @@ -212,12 +195,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() bool QBluetoothDeviceDiscoveryAgentPrivate::isValid() const { - // isValid() - Qt does not use exceptions, but the ctor - // can fail to initialize some important data-members - // (and the error is probably not even related to Bluetooth at all) - // - say, allocation error - this is what meant here by valid/invalid. - return hostController && [hostController powerState] == kBluetoothHCIPowerStateON - && inquiry; + return hostController && [hostController powerState] == kBluetoothHCIPowerStateON; } bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const @@ -231,23 +209,56 @@ bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const return agentState != NonActive; } -void QBluetoothDeviceDiscoveryAgentPrivate::start() +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) { - Q_ASSERT_X(isValid(), Q_FUNC_INFO, "called on invalid device discovery agent"); - Q_ASSERT_X(!isActive(), Q_FUNC_INFO, "called on active device discovery agent"); - Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, - Q_FUNC_INFO, "called with an invalid Bluetooth adapter"); + Q_ASSERT(isValid()); + Q_ASSERT(!isActive()); + Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + Q_ASSERT(methods & (QBluetoothDeviceDiscoveryAgent::ClassicMethod + | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)); + + requestedMethods = methods; if (stopPending) { startPending = true; return; } - agentState = ClassicScan; + // This function (re)starts the scan(s) from the scratch; + // starting from Classic if it's in 'methods' (or LE scan if not). + agentState = NonActive; discoveredDevices.clear(); setError(QBluetoothDeviceDiscoveryAgent::NoError); + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) + return startClassic(); + + startLE(); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::startClassic() +{ + Q_ASSERT(isValid()); + Q_ASSERT(!isActive()); + Q_ASSERT(lastError == QBluetoothDeviceDiscoveryAgent::NoError); + Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod); + Q_ASSERT(agentState == NonActive); + + if (!inquiry) { + // The first Classic scan for this DDA. + inquiry.reset([[DeviceInquiryObjC alloc]initWithDelegate:this]); + if (!inquiry) { + qCCritical(QT_BT_OSX) << "failed to initialize an Classic device inquiry"; + setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED)); + emit q_ptr->error(lastError); + return; + } + } + + agentState = ClassicScan; + const IOReturn res = [inquiry start]; if (res != kIOReturnSuccess) { setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED)); @@ -258,13 +269,29 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() void QBluetoothDeviceDiscoveryAgentPrivate::startLE() { - Q_ASSERT_X(isValid(), Q_FUNC_INFO, "called on invalid device discovery agent"); - Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, - Q_FUNC_INFO, "called with an invalid Bluetooth adapter"); + Q_ASSERT(isValid()); + Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); using namespace OSXBluetooth; - inquiryLE.reset([[LEDeviceInquiryObjC alloc] init]); + QScopedPointer<LECBManagerNotifier> notifier(new LECBManagerNotifier); + // Connections: + using ErrMemFunPtr = void (LECBManagerNotifier::*)(QBluetoothDeviceDiscoveryAgent::Error); + notifier->connect(notifier.data(), ErrMemFunPtr(&LECBManagerNotifier::CBManagerError), + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError); + notifier->connect(notifier.data(), &LECBManagerNotifier::LEnotSupported, + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported); + notifier->connect(notifier.data(), &LECBManagerNotifier::discoveryFinished, + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished); + using DeviceMemFunPtr = void (QBluetoothDeviceDiscoveryAgentPrivate::*)(const QBluetoothDeviceInfo &); + notifier->connect(notifier.data(), &LECBManagerNotifier::deviceDiscovered, + this, DeviceMemFunPtr(&QBluetoothDeviceDiscoveryAgentPrivate::deviceFound)); + + // Check queue and create scanner: + inquiryLE.reset([[LEDeviceInquiryObjC alloc] initWithNotifier:notifier.data()]); + if (inquiryLE) + notifier.take(); // Whatever happens next, inquiryLE is already the owner ... dispatch_queue_t leQueue(qt_LE_queue()); if (!leQueue || !inquiryLE) { @@ -272,18 +299,15 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE() QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED_LE)); agentState = NonActive; emit q_ptr->error(lastError); + return; } + // Now start in on LE queue: agentState = LEScan; - // CoreBluetooth does not have a timeout. We start a timer here - // and check if scan is active/finished/finished with error(s). - timer.reset(new OSXBluetooth::DDATimerHandler(this)); - timer->start(2000); - // We need the local variable so that it's retained ... LEDeviceInquiryObjC *inq = inquiryLE.data(); dispatch_async(leQueue, ^{ - [inq start]; + [inq startWithTimeout:lowEnergySearchTimeout]; }); } @@ -305,7 +329,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop() if (agentState == ClassicScan) { const IOReturn res = [inquiry stop]; if (res != kIOReturnSuccess) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to stop"; + qCWarning(QT_BT_OSX) << "failed to stop"; startPending = prevStart; stopPending = false; setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STOPPED)); @@ -316,7 +340,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop() Q_ASSERT(leQueue); // We need the local variable so that it's retained ... LEDeviceInquiryObjC *inq = inquiryLE.data(); - dispatch_async(leQueue, ^{ + dispatch_sync(leQueue, ^{ [inq stop]; }); // We consider LE scan to be stopped immediately and @@ -341,13 +365,17 @@ void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished(IOBluetoothDeviceInq } else if (startPending) { startPending = false; stopPending = false; - start(); + start(requestedMethods); } else { // We can be here _only_ if a classic scan - // finished in a normal way (not cancelled). + // finished in a normal way (not cancelled) + // and requestedMethods includes LowEnergyMethod. // startLE() will take care of old devices // not supporting Bluetooth 4.0. - startLE(); + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) + startLE(); + else + emit q_ptr->finished(); } } @@ -379,7 +407,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(IOBluetoothDeviceInquiry // Let's collect some info about this device: const QBluetoothAddress deviceAddress(OSXBluetooth::qt_address([device getAddress])); if (deviceAddress.isNull()) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "invalid Bluetooth address"; + qCWarning(QT_BT_OSX) << "invalid Bluetooth address"; return; } @@ -409,8 +437,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(IOReturn error, const QStri setError(QBluetoothDeviceDiscoveryAgent::UnknownError, text); } -void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, - const QString &text) +void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, const QString &text) { lastError = error; @@ -437,53 +464,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAg } if (lastError != QBluetoothDeviceDiscoveryAgent::NoError) - qCDebug(QT_BT_OSX) << "error set: "<<errorString; -} - -void QBluetoothDeviceDiscoveryAgentPrivate::checkLETimeout() -{ - Q_ASSERT_X(agentState == LEScan, Q_FUNC_INFO, "invalid agent state"); - Q_ASSERT_X(inquiryLE, Q_FUNC_INFO, "LE device inquiry is nil"); - - using namespace OSXBluetooth; - - const LEInquiryState state([inquiryLE inquiryState]); - if (state == InquiryStarting || state == InquiryActive) - return; // Wait ... - - if (state == ErrorPoweredOff) - return LEinquiryError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); - - if (state == ErrorLENotSupported) - return LEnotSupported(); - - if (state == InquiryFinished) { - // Process found devices if any ... - const QList<QBluetoothDeviceInfo> leDevices([inquiryLE discoveredDevices]); - foreach (const QBluetoothDeviceInfo &info, leDevices) { - // We were cancelled on a previous device discovered signal ... - if (agentState != LEScan) - break; - deviceFound(info); - } - - if (agentState == LEScan) - LEinquiryFinished(); - return; - } - - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected inquiry state in LE timeout"; - // Actually, this deserves an assert :) + qCDebug(QT_BT_OSX) << "error set:"<<errorString; } void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error) { - // At the moment the only error reported 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(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError); + Q_ASSERT(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError + || error == QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); - timer->stop(); inquiryLE.reset(); + + startPending = false; + stopPending = false; agentState = NonActive; setError(error); emit q_ptr->error(lastError); @@ -491,9 +483,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDisco void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported() { - // Not supported is not an error (we still have 'Classic'). qCDebug(QT_BT_OSX) << "no Bluetooth LE support"; - LEinquiryFinished(); + + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + // Having both Classic | LE means this is not an error. + LEinquiryFinished(); + } else { + // In the past this was never an error, that's why we have + // LEnotSupported as a special method. But now, since + // we can have separate Classic/LE scans, we have to report it + // as UnsupportedDiscoveryMethod. + LEinquiryError(QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); + } } void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished() @@ -501,7 +502,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished() // The same logic as in inquiryFinished, but does not start LE scan. agentState = NonActive; inquiryLE.reset(); - timer->stop(); if (stopPending && !startPending) { stopPending = false; @@ -509,7 +509,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished() } else if (startPending) { startPending = false; stopPending = false; - start(); //Start from a classic scan again. + start(requestedMethods); //Start again. } else { emit q_ptr->finished(); } @@ -569,7 +569,7 @@ QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inqu return d_ptr->inquiryType; } -void QBluetoothDeviceDiscoveryAgent::setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type) +void QBluetoothDeviceDiscoveryAgent::setInquiryType(InquiryType type) { d_ptr->inquiryType = type; } @@ -579,12 +579,33 @@ QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() return d_ptr->discoveredDevices; } +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ + return ClassicMethod | LowEnergyMethod; +} + void QBluetoothDeviceDiscoveryAgent::start() { + start(supportedDiscoveryMethods()); +} + +void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods) +{ + if (methods == NoMethod) + return; + + if ((supportedDiscoveryMethods() & methods) != methods) { + d_ptr->lastError = UnsupportedDiscoveryMethod; + d_ptr->errorString = tr("One or more device discovery methods " + "are not supported on this platform"); + emit error(d_ptr->lastError); + return; + } + if (d_ptr->lastError != InvalidBluetoothAdapterError) { if (d_ptr->isValid()) { if (!isActive()) - d_ptr->start(); + d_ptr->start(methods); } else { // We previously failed to initialize d_ptr correctly: // either some memory allocation problem or @@ -621,4 +642,21 @@ QString QBluetoothDeviceDiscoveryAgent::errorString() const return d_ptr->errorString; } +void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout) +{ + // cannot deliberately turn it off + if (timeout < 0) { + qCDebug(QT_BT_OSX) << "The Bluetooth Low Energy device discovery timeout cannot be negative."; + return; + } + + d_ptr->lowEnergySearchTimeout = timeout; + return; +} + +int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const +{ + return d_ptr->lowEnergySearchTimeout; +} + QT_END_NAMESPACE |