diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-07-20 16:20:03 +0400 |
---|---|---|
committer | Alex Blasche <alexander.blasche@digia.com> | 2014-09-01 08:34:03 +0200 |
commit | fc4ed403dc20507d3c3f137b4acb957e2eef3c41 (patch) | |
tree | 323acfba9252ab434ba8fba8956a15d8def37e90 /src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp | |
parent | b2dcf3f5a2fb5a32eb6125024fb2070725fd87cc (diff) |
Implement the QBluetoothDeviceDiscoveryAgent class on Windows
Change-Id: I74eaf9acedbcd5b601ff3a6feef21869dbbf9bd9
Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp | 183 |
1 files changed, 172 insertions, 11 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp index 863ae74b..94c62ba1 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtBluetooth module of the Qt Toolkit. @@ -48,35 +49,195 @@ QT_BEGIN_NAMESPACE +struct NativeFindResult +{ + NativeFindResult(); + + BLUETOOTH_DEVICE_INFO deviceInfo; + HBLUETOOTH_DEVICE_FIND findHandle; + DWORD errorCode; +}; +Q_DECLARE_METATYPE(NativeFindResult) + +NativeFindResult::NativeFindResult() + : findHandle(NULL) + , errorCode(ERROR_SUCCESS) +{ + ::ZeroMemory(&deviceInfo, sizeof(deviceInfo)); + deviceInfo.dwSize = sizeof(deviceInfo); +} + QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( - const QBluetoothAddress &deviceAdapter, - QBluetoothDeviceDiscoveryAgent *parent) - : q_ptr(parent) + const QBluetoothAddress &deviceAdapter, + QBluetoothDeviceDiscoveryAgent *parent) + : QBluetoothLocalDevicePrivateData(deviceAdapter) + , inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry) + , lastError(QBluetoothDeviceDiscoveryAgent::NoError) + , findWatcher(0) + , pendingCancel(false) + , pendingStart(false) + , q_ptr(parent) { - Q_UNUSED(deviceAdapter); - inquiryType = QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry; - lastError = QBluetoothDeviceDiscoveryAgent::NoError; } QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() { + if (isRunning()) { + stop(); + findWatcher->waitForFinished(); + } } bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const { - return false; + if (pendingStart) + return true; + if (pendingCancel) + return false; + + return isRunning(); } void QBluetoothDeviceDiscoveryAgentPrivate::start() { Q_Q(QBluetoothDeviceDiscoveryAgent); - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr("No Bluetooth device available"); - emit q->error(QBluetoothDeviceDiscoveryAgent::InputOutputError); + + if (pendingCancel == true) { + pendingStart = true; + return; + } + + discoveredDevices.clear(); + + if (!findWatcher) { + findWatcher = new QFutureWatcher<QVariant>(q); + QObject::connect(findWatcher, SIGNAL(finished()), q, SLOT(_q_handleFindResult())); + } + + const QFuture<QVariant> future = QtConcurrent::run(findFirstDevice, deviceHandle); + findWatcher->setFuture(future); } void QBluetoothDeviceDiscoveryAgentPrivate::stop() { + if (!isRunning()) + return; + + pendingCancel = true; + pendingStart = false; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_handleFindResult() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + const QVariant result = findWatcher->result(); + const NativeFindResult nativeFindResult = result.value<NativeFindResult>(); + + if (nativeFindResult.errorCode == ERROR_SUCCESS + || nativeFindResult.errorCode == ERROR_NO_MORE_ITEMS) { + + if (pendingCancel && !pendingStart) { + emit q->canceled(); + pendingCancel = false; + } else if (pendingStart) { + pendingCancel = false; + pendingStart = false; + start(); + } else { + if (nativeFindResult.errorCode == ERROR_NO_MORE_ITEMS) { + emit q->finished(); + } else { + processDiscoveredDevices(nativeFindResult.deviceInfo); + const QFuture<QVariant> future = + QtConcurrent::run(findNextDevice, nativeFindResult.findHandle); + findWatcher->setFuture(future); + return; + } + } + + } else { + handleErrors(nativeFindResult.errorCode); + pendingCancel = false; + pendingStart = false; + } + + findClose(nativeFindResult.findHandle); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices( + const BLUETOOTH_DEVICE_INFO &info) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + QBluetoothDeviceInfo deviceInfo( + QBluetoothAddress(info.Address.ullLong), + QString::fromWCharArray(info.szName), + info.ulClassofDevice); + + if (info.fRemembered) + deviceInfo.setCached(true); + + discoveredDevices.append(deviceInfo); + emit q->deviceDiscovered(deviceInfo); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::handleErrors(DWORD errorCode) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + lastError = (errorCode == ERROR_INVALID_HANDLE) ? + QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError + : QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = qt_error_string(errorCode); + emit q->error(lastError); +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isRunning() const +{ + return findWatcher && findWatcher->isRunning(); +} + +QVariant QBluetoothDeviceDiscoveryAgentPrivate::findFirstDevice(HANDLE radioHandle) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS searchParams; + ::ZeroMemory(&searchParams, sizeof(searchParams)); + searchParams.dwSize = sizeof(searchParams); + searchParams.cTimeoutMultiplier = 10; // 12.8 sec + searchParams.fIssueInquiry = TRUE; + searchParams.fReturnAuthenticated = TRUE; + searchParams.fReturnConnected = TRUE; + searchParams.fReturnRemembered = TRUE; + searchParams.fReturnUnknown = TRUE; + searchParams.hRadio = radioHandle; + + NativeFindResult nativeFindResult; + nativeFindResult.findHandle = ::BluetoothFindFirstDevice( + &searchParams, &nativeFindResult.deviceInfo); + if (!nativeFindResult.findHandle) + nativeFindResult.errorCode = ::GetLastError(); + + QVariant result; + result.setValue(nativeFindResult); + return result; +} + +QVariant QBluetoothDeviceDiscoveryAgentPrivate::findNextDevice(HBLUETOOTH_DEVICE_FIND findHandle) +{ + NativeFindResult nativeFindResult; + nativeFindResult.findHandle = findHandle; + if (!::BluetoothFindNextDevice(findHandle, &nativeFindResult.deviceInfo)) + nativeFindResult.errorCode = ::GetLastError(); + + QVariant result; + result.setValue(nativeFindResult); + return result; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::findClose(HBLUETOOTH_DEVICE_FIND findHandle) +{ + if (findHandle) + ::BluetoothFindDeviceClose(findHandle); } QT_END_NAMESPACE |