summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-07-20 16:20:03 +0400
committerAlex Blasche <alexander.blasche@digia.com>2014-09-01 08:34:03 +0200
commitfc4ed403dc20507d3c3f137b4acb957e2eef3c41 (patch)
tree323acfba9252ab434ba8fba8956a15d8def37e90 /src/bluetooth/qbluetoothdevicediscoveryagent_win.cpp
parentb2dcf3f5a2fb5a32eb6125024fb2070725fd87cc (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.cpp183
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