summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2018-07-25 14:42:06 +0200
committerAlex Blasche <alexander.blasche@qt.io>2018-07-25 14:42:18 +0200
commit25638b02766ae3109bfc83b3249e6d0dc9e21bdb (patch)
tree8ac8f0cd544dd39da674657940d6c509ea94721c /src
parentfc2a206322f6190226ebc1f04062f2c9170f0bac (diff)
parentb19148f9a0f820630bd83432d96117e9598c315d (diff)
Merge remote-tracking branch 'gerrit/dev' into btlebtle
Diffstat (limited to 'src')
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java39
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java38
-rw-r--r--src/android/nfc/nfc.pro3
-rw-r--r--src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java5
-rw-r--r--src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver.java72
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver.cpp4
-rw-r--r--src/bluetooth/android/inputstreamthread.cpp4
-rw-r--r--src/bluetooth/android/inputstreamthread_p.h6
-rw-r--r--src/bluetooth/android/lowenergynotificationhub.cpp4
-rw-r--r--src/bluetooth/android/lowenergynotificationhub_p.h3
-rw-r--r--src/bluetooth/bluetooth.pro46
-rw-r--r--src/bluetooth/bluez/adapter.cpp4
-rw-r--r--src/bluetooth/bluez/adapter_p.h60
-rw-r--r--src/bluetooth/bluez/agent.cpp4
-rw-r--r--src/bluetooth/bluez/agent_p.h9
-rw-r--r--src/bluetooth/bluez/bluetoothmanagement.cpp2
-rw-r--r--src/bluetooth/bluez/bluez.pri6
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp182
-rw-r--r--src/bluetooth/bluez/bluez5_helper_p.h4
-rw-r--r--src/bluetooth/bluez/bluez_data_p.h4
-rw-r--r--src/bluetooth/bluez/device.cpp4
-rw-r--r--src/bluetooth/bluez/device1_bluez5.cpp1
-rw-r--r--src/bluetooth/bluez/device1_bluez5_p.h1
-rw-r--r--src/bluetooth/bluez/device_p.h34
-rw-r--r--src/bluetooth/bluez/gattchar1.cpp26
-rw-r--r--src/bluetooth/bluez/gattchar1_p.h93
-rw-r--r--src/bluetooth/bluez/gattdesc1.cpp26
-rw-r--r--src/bluetooth/bluez/gattdesc1_p.h73
-rw-r--r--src/bluetooth/bluez/gattservice1.cpp26
-rw-r--r--src/bluetooth/bluez/gattservice1_p.h63
-rwxr-xr-xsrc/bluetooth/bluez/generate8
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp6
-rw-r--r--src/bluetooth/bluez/manager.cpp4
-rw-r--r--src/bluetooth/bluez/manager_p.h18
-rw-r--r--src/bluetooth/bluez/obex_agent.cpp6
-rw-r--r--src/bluetooth/bluez/obex_agent_p.h11
-rw-r--r--src/bluetooth/bluez/obex_client.cpp4
-rw-r--r--src/bluetooth/bluez/obex_client1_bluez5_p.h14
-rw-r--r--src/bluetooth/bluez/obex_client_p.h30
-rw-r--r--src/bluetooth/bluez/obex_manager.cpp4
-rw-r--r--src/bluetooth/bluez/obex_manager_p.h18
-rw-r--r--src/bluetooth/bluez/obex_objectpush1_bluez5.cpp4
-rw-r--r--src/bluetooth/bluez/obex_objectpush1_bluez5_p.h22
-rw-r--r--src/bluetooth/bluez/obex_transfer.cpp4
-rw-r--r--src/bluetooth/bluez/obex_transfer1_bluez5_p.h16
-rw-r--r--src/bluetooth/bluez/obex_transfer_p.h14
-rw-r--r--src/bluetooth/bluez/objectmanager.cpp4
-rw-r--r--src/bluetooth/bluez/objectmanager_p.h12
-rw-r--r--src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml22
-rw-r--r--src/bluetooth/bluez/org.bluez.GattDescriptor1.xml18
-rw-r--r--src/bluetooth/bluez/org.bluez.GattService1.xml9
-rw-r--r--src/bluetooth/bluez/profile1.cpp4
-rw-r--r--src/bluetooth/bluez/profile1_p.h14
-rw-r--r--src/bluetooth/bluez/properties.cpp4
-rw-r--r--src/bluetooth/bluez/properties_p.h16
-rw-r--r--src/bluetooth/bluez/remotedevicemanager.cpp5
-rw-r--r--src/bluetooth/bluez/service.cpp4
-rw-r--r--src/bluetooth/bluez/service_p.h28
-rw-r--r--src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp16
-rw-r--r--src/bluetooth/doc/snippets/doc_src_qtbluetooth.qml16
-rw-r--r--src/bluetooth/doc/src/bluetooth-index.qdoc7
-rw-r--r--src/bluetooth/doc/src/bluetooth-qml.qdoc2
-rw-r--r--src/bluetooth/osx/osxbt.pri7
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm226
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager_p.h23
-rw-r--r--src/bluetooth/osx/osxbtgcdtimer.mm111
-rw-r--r--src/bluetooth/osx/osxbtgcdtimer_p.h94
-rw-r--r--src/bluetooth/osx/osxbtledeviceinquiry.mm119
-rw-r--r--src/bluetooth/osx/osxbtledeviceinquiry_p.h18
-rw-r--r--src/bluetooth/osx/osxbtperipheralmanager.mm5
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp30
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h5
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp76
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.cpp7
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp24
-rw-r--r--src/bluetooth/qbluetoothserver.cpp5
-rw-r--r--src/bluetooth/qbluetoothserver_android.cpp2
-rw-r--r--src/bluetooth/qbluetoothserver_osx.mm2
-rw-r--r--src/bluetooth/qbluetoothserver_p.h2
-rw-r--r--src/bluetooth/qbluetoothserver_winrt.cpp2
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.cpp3
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_p.h4
-rw-r--r--src/bluetooth/qbluetoothserviceinfo.cpp4
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_winrt.cpp7
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp251
-rw-r--r--src/bluetooth/qbluetoothsocket.h26
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp156
-rw-r--r--src/bluetooth/qbluetoothsocket_android_p.h145
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp169
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez_p.h108
-rw-r--r--src/bluetooth/qbluetoothsocket_bluezdbus.cpp (renamed from src/bluetooth/qbluetoothsocket_p.cpp)77
-rw-r--r--src/bluetooth/qbluetoothsocket_bluezdbus_p.h104
-rw-r--r--src/bluetooth/qbluetoothsocket_dummy.cpp208
-rw-r--r--src/bluetooth/qbluetoothsocket_dummy_p.h107
-rw-r--r--src/bluetooth/qbluetoothsocket_osx.mm11
-rw-r--r--src/bluetooth/qbluetoothsocket_osx_p.h5
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt.cpp183
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt_p.h134
-rw-r--r--src/bluetooth/qbluetoothsocketbase.cpp54
-rw-r--r--src/bluetooth/qbluetoothsocketbase_p.h (renamed from src/bluetooth/qbluetoothsocket_p.h)242
-rw-r--r--src/bluetooth/qbluetoothuuid.h3
-rw-r--r--src/bluetooth/qleadvertiser_bluez.cpp2
-rw-r--r--src/bluetooth/qlowenergycharacteristic.h5
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp319
-rw-r--r--src/bluetooth/qlowenergycontroller_android.cpp103
-rw-r--r--src/bluetooth/qlowenergycontroller_android_p.h171
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp313
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez_p.h357
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus.cpp1090
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus_p.h191
-rw-r--r--src/bluetooth/qlowenergycontroller_osx.mm2
-rw-r--r--src/bluetooth/qlowenergycontroller_osx_p.h2
-rw-r--r--src/bluetooth/qlowenergycontroller_p.cpp41
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h424
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp105
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h149
-rw-r--r--src/bluetooth/qlowenergycontrollerbase.cpp323
-rw-r--r--src/bluetooth/qlowenergycontrollerbase_p.h186
-rw-r--r--src/bluetooth/qlowenergydescriptor.cpp4
-rw-r--r--src/bluetooth/qlowenergydescriptor.h5
-rw-r--r--src/bluetooth/qlowenergyservice.cpp36
-rw-r--r--src/bluetooth/qlowenergyservice.h3
-rw-r--r--src/bluetooth/qlowenergyserviceprivate.cpp2
-rw-r--r--src/bluetooth/qtbluetoothglobal_p.h6
-rw-r--r--src/imports/bluetooth/plugin.cpp15
-rw-r--r--src/imports/bluetooth/plugins.qmltypes8
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp36
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothservice.cpp3
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothsocket.cpp30
-rw-r--r--src/imports/nfc/plugin.cpp14
-rw-r--r--src/imports/nfc/plugins.qmltypes7
-rw-r--r--src/imports/nfc/qdeclarativendeffilter.cpp2
-rw-r--r--src/nfc/android/androidjninfc.cpp5
-rw-r--r--src/nfc/android/androidjninfc_p.h1
-rw-r--r--src/nfc/doc/snippets/doc_src_qtnfc.cpp14
-rw-r--r--src/nfc/doc/snippets/doc_src_qtnfc.qml16
-rw-r--r--src/nfc/doc/snippets/foorecord.cpp16
-rw-r--r--src/nfc/doc/snippets/foorecord.h16
-rw-r--r--src/nfc/doc/snippets/main.cpp16
-rw-r--r--src/nfc/doc/snippets/nfc.cpp16
-rw-r--r--src/nfc/doc/src/nfc-index.qdoc9
-rw-r--r--src/nfc/doc/src/nfc-qml.qdoc2
-rw-r--r--src/nfc/neard/neard_helper.cpp8
-rw-r--r--src/nfc/qllcpsocket_android_p.cpp6
-rw-r--r--src/nfc/qndefnfcsmartposterrecord.cpp2
-rw-r--r--src/nfc/qndefnfctextrecord.cpp2
-rw-r--r--src/nfc/qndefnfcurirecord.cpp2
-rw-r--r--src/nfc/qnearfieldmanager.cpp65
-rw-r--r--src/nfc/qnearfieldmanager.h9
-rw-r--r--src/nfc/qnearfieldmanager_android.cpp67
-rw-r--r--src/nfc/qnearfieldmanager_android_p.h1
-rw-r--r--src/nfc/qnearfieldmanager_emulator.cpp4
-rw-r--r--src/nfc/qnearfieldmanager_neard.cpp23
-rw-r--r--src/nfc/qnearfieldmanager_neard_p.h2
-rw-r--r--src/nfc/qnearfieldmanager_p.h6
-rw-r--r--src/nfc/qnearfieldsharemanager.cpp2
-rw-r--r--src/nfc/qnearfieldtagtype1.cpp8
-rw-r--r--src/nfc/qnearfieldtarget.cpp13
-rw-r--r--src/nfc/qnearfieldtarget.h2
-rw-r--r--src/nfc/qnearfieldtarget_android.cpp62
-rw-r--r--src/nfc/qnearfieldtarget_emulator.cpp20
-rw-r--r--src/nfc/qnearfieldtarget_neard_p.h20
-rw-r--r--src/nfc/qqmlndefrecord.cpp2
163 files changed, 6335 insertions, 2025 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
index 1b527ae3..4063537b 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
@@ -1141,16 +1141,24 @@ public class QtBluetoothLE {
if (handle == HANDLE_FOR_MTU_EXCHANGE)
return;
- GattEntry entry = entries.get(handle);
- if (entry == null)
- return;
- if (entry.valueKnown)
- return;
- entry.valueKnown = true;
+ try {
+ synchronized (this) {
- GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
- if (serviceEntry != null && serviceEntry.endHandle == handle)
- finishCurrentServiceDiscovery(entry.associatedServiceHandle);
+ GattEntry entry = entries.get(handle);
+ if (entry == null)
+ return;
+ if (entry.valueKnown)
+ return;
+ entry.valueKnown = true;
+
+ GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
+ if (serviceEntry != null && serviceEntry.endHandle == handle)
+ finishCurrentServiceDiscovery(entry.associatedServiceHandle);
+ }
+ } catch (IndexOutOfBoundsException outOfBounds) {
+ Log.w(TAG, "interruptCurrentIO(): Unknown gatt entry, index: "
+ + handle + " size: " + entries.size());
+ }
}
/*
@@ -1271,9 +1279,16 @@ public class QtBluetoothLE {
}
// last entry of current discovery run?
- GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
- if (serviceEntry.endHandle == handle)
- finishCurrentServiceDiscovery(entry.associatedServiceHandle);
+ synchronized (this) {
+ try {
+ GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
+ if (serviceEntry.endHandle == handle)
+ finishCurrentServiceDiscovery(entry.associatedServiceHandle);
+ } catch (IndexOutOfBoundsException outOfBounds) {
+ Log.w(TAG, "performNextIO(): Unknown service for entry, index: "
+ + entry.associatedServiceHandle + " size: " + entries.size());
+ }
+ }
} else {
int errorCode = 0;
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java
index 00217904..cdd16686 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java
@@ -82,6 +82,12 @@ public class QtBluetoothLEServer {
private BluetoothGattServer mGattServer = null;
private BluetoothLeAdvertiser mLeAdvertiser = null;
+ private String mRemoteName = "";
+ public String remoteName() { return mRemoteName; }
+
+ private String mRemoteAddress = "";
+ public String remoteAddress() { return mRemoteAddress; }
+
/*
As per Bluetooth specification each connected device can have individual and persistent
Client characteristic configurations (see Bluetooth Spec 5.0 Vol 3 Part G 3.3.3.3)
@@ -207,7 +213,6 @@ public class QtBluetoothLEServer {
return;
}
- mGattServer = manager.openGattServer(qtContext, mGattServerListener);
mLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
if (!mBluetoothAdapter.isMultipleAdvertisementSupported())
@@ -223,7 +228,7 @@ public class QtBluetoothLEServer {
{
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
- Log.w(TAG, "Our gatt server connection state changed, new state: " + newState);
+ Log.w(TAG, "Our gatt server connection state changed, new state: " + newState + " " + status);
super.onConnectionStateChange(device, status, newState);
int qtControllerState = 0;
@@ -231,6 +236,7 @@ public class QtBluetoothLEServer {
case BluetoothProfile.STATE_DISCONNECTED:
qtControllerState = 0; // QLowEnergyController::UnconnectedState
clientCharacteristicManager.markDeviceConnectivity(device, false);
+ mGattServer.close();
break;
case BluetoothProfile.STATE_CONNECTED:
clientCharacteristicManager.markDeviceConnectivity(device, true);
@@ -238,6 +244,9 @@ public class QtBluetoothLEServer {
break;
}
+ mRemoteName = device.getName();
+ mRemoteAddress = device.getAddress();
+
int qtErrorCode;
switch (status) {
case BluetoothGatt.GATT_SUCCESS:
@@ -392,10 +401,18 @@ public class QtBluetoothLEServer {
public boolean connectServer()
{
- if (mGattServer == null)
+ if (mGattServer != null)
+ return true;
+
+ BluetoothManager manager = (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE);
+ if (manager == null) {
+ Log.w(TAG, "Bluetooth service not available.");
return false;
+ }
- return true;
+ mGattServer = manager.openGattServer(qtContext, mGattServerListener);
+
+ return (mGattServer != null);
}
public void disconnectServer()
@@ -404,6 +421,10 @@ public class QtBluetoothLEServer {
return;
mGattServer.close();
+ mGattServer = null;
+
+ mRemoteName = mRemoteAddress = "";
+ leServerConnectionStateChange(qtObject, 0 /*NoError*/, 0 /*QLowEnergyController::UnconnectedState*/);
}
public boolean startAdvertising(AdvertiseData advertiseData,
@@ -413,7 +434,10 @@ public class QtBluetoothLEServer {
if (mLeAdvertiser == null)
return false;
- connectServer();
+ if (!connectServer()) {
+ Log.w(TAG, "Server::startAdvertising: Cannot open GATT server");
+ return false;
+ }
Log.w(TAG, "Starting to advertise.");
mLeAdvertiser.startAdvertising(settings, advertiseData, scanResponse, mAdvertiseListener);
@@ -432,8 +456,10 @@ public class QtBluetoothLEServer {
public void addService(BluetoothGattService service)
{
- if (mGattServer == null)
+ if (!connectServer()) {
+ Log.w(TAG, "Server::addService: Cannot open GATT server");
return;
+ }
mGattServer.addService(service);
}
diff --git a/src/android/nfc/nfc.pro b/src/android/nfc/nfc.pro
index 89026b75..a725fb7d 100644
--- a/src/android/nfc/nfc.pro
+++ b/src/android/nfc/nfc.pro
@@ -7,7 +7,8 @@ PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc
JAVACLASSPATH += $$PWD/src/
JAVASOURCES += \
- $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java
+ $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java \
+ $$PWD/src/org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver.java \
# install
target.path = $$[QT_INSTALL_PREFIX]/jar
diff --git a/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java
index 345b87d3..6b0fbcbd 100644
--- a/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java
+++ b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java
@@ -169,6 +169,11 @@ public class QtNfc
return m_adapter.isEnabled();
}
+ static public boolean isSupported()
+ {
+ return (m_adapter != null);
+ }
+
static public Intent getStartIntent()
{
Log.d(TAG, "getStartIntent");
diff --git a/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver.java b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver.java
new file mode 100644
index 00000000..ea650ede
--- /dev/null
+++ b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver.java
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Governikus GmbH & Co. KG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNfc 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 The Qt Company. For licensing terms
+** 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android.nfc;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+
+
+public class QtNfcBroadcastReceiver extends BroadcastReceiver
+{
+ private Context qtContext;
+
+ public QtNfcBroadcastReceiver(Context context)
+ {
+ qtContext = context;
+ IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ qtContext.registerReceiver(this, filter);
+ }
+
+ public void unregisterReceiver()
+ {
+ qtContext.unregisterReceiver(this);
+ }
+
+ public void onReceive(Context context, Intent intent)
+ {
+ final int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
+ jniOnReceive(state);
+ }
+
+ public native void jniOnReceive(int state);
+}
diff --git a/src/bluetooth/android/androidbroadcastreceiver.cpp b/src/bluetooth/android/androidbroadcastreceiver.cpp
index 50465017..c64e61ff 100644
--- a/src/bluetooth/android/androidbroadcastreceiver.cpp
+++ b/src/bluetooth/android/androidbroadcastreceiver.cpp
@@ -54,9 +54,7 @@ AndroidBroadcastReceiver::AndroidBroadcastReceiver(QObject* parent)
: QObject(parent), valid(false)
{
// get Qt Context
- // TODO: replace with QtAndroidPrivate::context() introduced by Qt 5.8
- contextObject = QAndroidJniObject(QtAndroidPrivate::activity()
- ? QtAndroidPrivate::activity() : QtAndroidPrivate::service());
+ contextObject = QAndroidJniObject(QtAndroidPrivate::context());
broadcastReceiverObject = QAndroidJniObject("org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver");
if (!broadcastReceiverObject.isValid())
diff --git a/src/bluetooth/android/inputstreamthread.cpp b/src/bluetooth/android/inputstreamthread.cpp
index 982c477b..1cc353a3 100644
--- a/src/bluetooth/android/inputstreamthread.cpp
+++ b/src/bluetooth/android/inputstreamthread.cpp
@@ -42,13 +42,13 @@
#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "android/inputstreamthread_p.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_android_p.h"
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
-InputStreamThread::InputStreamThread(QBluetoothSocketPrivate *socket)
+InputStreamThread::InputStreamThread(QBluetoothSocketPrivateAndroid *socket)
: QObject(), m_socket_p(socket), expectClosure(false)
{
}
diff --git a/src/bluetooth/android/inputstreamthread_p.h b/src/bluetooth/android/inputstreamthread_p.h
index a6ee0655..060b2acf 100644
--- a/src/bluetooth/android/inputstreamthread_p.h
+++ b/src/bluetooth/android/inputstreamthread_p.h
@@ -59,13 +59,13 @@
QT_BEGIN_NAMESPACE
-class QBluetoothSocketPrivate;
+class QBluetoothSocketPrivateAndroid;
class InputStreamThread : public QObject
{
Q_OBJECT
public:
- explicit InputStreamThread(QBluetoothSocketPrivate *socket_p);
+ explicit InputStreamThread(QBluetoothSocketPrivateAndroid *socket_p);
qint64 bytesAvailable() const;
bool canReadLine() const;
@@ -82,7 +82,7 @@ signals:
void error(int errorCode);
private:
- QBluetoothSocketPrivate *m_socket_p;
+ QBluetoothSocketPrivateAndroid *m_socket_p;
QAndroidJniObject javaInputStreamThread;
mutable QMutex m_mutex;
bool expectClosure;
diff --git a/src/bluetooth/android/lowenergynotificationhub.cpp b/src/bluetooth/android/lowenergynotificationhub.cpp
index 9f90e3de..b37e3e0c 100644
--- a/src/bluetooth/android/lowenergynotificationhub.cpp
+++ b/src/bluetooth/android/lowenergynotificationhub.cpp
@@ -70,7 +70,7 @@ LowEnergyNotificationHub::LowEnergyNotificationHub(const QBluetoothAddress &remo
jBluetoothLe = QAndroidJniObject("org/qtproject/qt5/android/bluetooth/QtBluetoothLE",
"(Ljava/lang/String;Landroid/content/Context;)V",
address.object<jstring>(),
- QtAndroidPrivate::activity() ? QtAndroidPrivate::activity() : QtAndroidPrivate::service());
+ QtAndroidPrivate::context());
}
if (env->ExceptionCheck() || !jBluetoothLe.isValid()) {
@@ -84,7 +84,7 @@ LowEnergyNotificationHub::LowEnergyNotificationHub(const QBluetoothAddress &remo
lock.lockForWrite();
while (true) {
- javaToCtoken = QRandomGenerator::get32();
+ javaToCtoken = QRandomGenerator::global()->generate();
if (!hubMap()->contains(javaToCtoken))
break;
}
diff --git a/src/bluetooth/android/lowenergynotificationhub_p.h b/src/bluetooth/android/lowenergynotificationhub_p.h
index 4a384a8c..da651e68 100644
--- a/src/bluetooth/android/lowenergynotificationhub_p.h
+++ b/src/bluetooth/android/lowenergynotificationhub_p.h
@@ -56,10 +56,11 @@
#include <QtCore/private/qjnihelpers_p.h>
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtBluetooth/QBluetoothAddress>
+#include <QtBluetooth/QLowEnergyController>
+#include <QtBluetooth/QLowEnergyService>
#include <jni.h>
#include <QtBluetooth/QLowEnergyCharacteristic>
-#include "qlowenergycontroller_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index 1ef7406b..884dbebf 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -40,13 +40,13 @@ PRIVATE_HEADERS += \
qbluetoothserviceinfo_p.h\
qbluetoothdevicediscoveryagent_p.h\
qbluetoothservicediscoveryagent_p.h\
- qbluetoothsocket_p.h\
+ qbluetoothsocketbase_p.h \
qbluetoothserver_p.h\
qbluetoothtransferreply_p.h \
qbluetoothtransferrequest_p.h \
qprivatelinearbuffer_p.h \
qbluetoothlocaldevice_p.h \
- qlowenergycontroller_p.h \
+ qlowenergycontrollerbase_p.h \
qlowenergyserviceprivate_p.h \
qleadvertiser_p.h \
lecmaccalculator_p.h
@@ -60,6 +60,7 @@ SOURCES += \
qbluetoothdevicediscoveryagent.cpp\
qbluetoothservicediscoveryagent.cpp\
qbluetoothsocket.cpp\
+ qbluetoothsocketbase.cpp \
qbluetoothserver.cpp \
qbluetoothlocaldevice.cpp \
qbluetooth.cpp \
@@ -76,6 +77,7 @@ SOURCES += \
qlowenergydescriptor.cpp \
qlowenergydescriptordata.cpp \
qlowenergycontroller.cpp \
+ qlowenergycontrollerbase.cpp \
qlowenergyserviceprivate.cpp
win32 {
@@ -87,19 +89,25 @@ qtConfig(bluez) {
QT_PRIVATE = concurrent
QT_FOR_PRIVATE += dbus
+ # do not link against QtNetwork but use inline qt_safe_* functions
+ INCLUDEPATH += $$QT.network_private.includes
+
include(bluez/bluez.pri)
PRIVATE_HEADERS += \
- qbluetoothtransferreply_bluez_p.h
+ qbluetoothtransferreply_bluez_p.h \
+ qbluetoothsocket_bluez_p.h \
+ qbluetoothsocket_bluezdbus_p.h
SOURCES += \
qbluetoothserviceinfo_bluez.cpp \
qbluetoothdevicediscoveryagent_bluez.cpp\
qbluetoothservicediscoveryagent_bluez.cpp \
qbluetoothsocket_bluez.cpp \
+ qbluetoothsocket_bluezdbus.cpp \
qbluetoothserver_bluez.cpp \
qbluetoothlocaldevice_bluez.cpp \
- qbluetoothtransferreply_bluez.cpp \
+ qbluetoothtransferreply_bluez.cpp
# old versions of Bluez do not have the required BTLE symbols
@@ -107,13 +115,20 @@ qtConfig(bluez) {
SOURCES += \
qleadvertiser_bluez.cpp \
qlowenergycontroller_bluez.cpp \
- lecmaccalculator.cpp
+ lecmaccalculator.cpp \
+ qlowenergycontroller_bluezdbus.cpp
+
+ PRIVATE_HEADERS += qlowenergycontroller_bluezdbus_p.h \
+ qlowenergycontroller_bluez_p.h
+
qtConfig(linux_crypto_api): DEFINES += CONFIG_LINUX_CRYPTO_API
} else {
DEFINES += QT_BLUEZ_NO_BTLE
include(dummy/dummy.pri)
SOURCES += \
qlowenergycontroller_p.cpp
+
+ PRIVATE_HEADERS += qlowenergycontroller_p.h
}
} else:android:!android-embedded {
@@ -137,6 +152,8 @@ qtConfig(bluez) {
qbluetoothserver_android.cpp \
qlowenergycontroller_android.cpp
+ PRIVATE_HEADERS += qlowenergycontroller_android_p.h \
+ qbluetoothsocket_android_p.h
} else:osx {
QT_PRIVATE = concurrent
DEFINES += QT_OSX_BLUETOOTH
@@ -164,11 +181,12 @@ qtConfig(bluez) {
SOURCES -= qbluetoothserviceinfo.cpp
SOURCES -= qbluetoothservicediscoveryagent.cpp
SOURCES -= qbluetoothsocket.cpp
+ SOURCES -= qbluetoothsocketbase.cpp
SOURCES -= qbluetoothserver.cpp
SOURCES -= qlowenergyservice_p.cpp
SOURCES -= qlowenergyservice.cpp
SOURCES -= qlowenergycontroller.cpp
- SOURCES -= qlowenergycontroller_p.cpp
+ SOURCES -= qlowenergycontrollerbase.cpp
} else:ios|tvos {
DEFINES += QT_IOS_BLUETOOTH
LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth
@@ -179,19 +197,21 @@ qtConfig(bluez) {
qlowenergyservice_osx.mm
PRIVATE_HEADERS += \
- qlowenergycontroller_osx_p.h
+ qlowenergycontroller_osx_p.h \
+ qbluetoothsocket_dummy_p.h
include(osx/osxbt.pri)
SOURCES += \
qbluetoothlocaldevice_p.cpp \
qbluetoothserviceinfo_p.cpp \
qbluetoothservicediscoveryagent_p.cpp \
- qbluetoothsocket_p.cpp \
+ qbluetoothsocket_dummy.cpp \
qbluetoothserver_p.cpp
SOURCES -= qbluetoothdevicediscoveryagent.cpp
SOURCES -= qlowenergyservice.cpp
SOURCES -= qlowenergycontroller.cpp
+ SOURCES -= qlowenergycontrollerbase.cpp
} else: qtConfig(winrt_bt) {
DEFINES += QT_WINRT_BLUETOOTH
!winrt {
@@ -211,6 +231,9 @@ qtConfig(bluez) {
qbluetoothsocket_winrt.cpp \
qlowenergycontroller_winrt.cpp
+ PRIVATE_HEADERS += qlowenergycontroller_winrt_p.h \
+ qbluetoothsocket_winrt_p.h
+
lessThan(WINDOWS_SDK_VERSION, 14393) {
DEFINES += QT_WINRT_LIMITED_SERVICEDISCOVERY
DEFINES += QT_UCRTVERSION=$$WINDOWS_SDK_VERSION
@@ -224,12 +247,15 @@ qtConfig(bluez) {
qbluetoothlocaldevice_p.cpp \
qbluetoothserviceinfo_p.cpp \
qbluetoothservicediscoveryagent_p.cpp \
- qbluetoothsocket_p.cpp \
+ qbluetoothsocket_dummy.cpp \
qbluetoothserver_p.cpp \
qlowenergycontroller_p.cpp
+
+ PRIVATE_HEADERS += qlowenergycontroller_p.h \
+ qbluetoothsocket_dummy_p.h
}
-winrt-*-msvc2015 {
+winrt {
MODULE_WINRT_CAPABILITIES_DEVICE += \
bluetooth.genericAttributeProfile \
bluetooth.rfcomm
diff --git a/src/bluetooth/bluez/adapter.cpp b/src/bluetooth/bluez/adapter.cpp
index 10b46f3b..eaea76f8 100644
--- a/src/bluetooth/bluez/adapter.cpp
+++ b/src/bluetooth/bluez/adapter.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/adapter_p.h b/src/bluetooth/bluez/adapter_p.h
index d9b6a0c7..236fe7e4 100644
--- a/src/bluetooth/bluez/adapter_p.h
+++ b/src/bluetooth/bluez/adapter_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef ADAPTER_P_H_1273205927
-#define ADAPTER_P_H_1273205927
+#ifndef ADAPTER_P_H
+#define ADAPTER_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.Adapter"; }
public:
- OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezAdapterInterface();
@@ -39,106 +39,106 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CancelDeviceCreation(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("CancelDeviceCreation"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("CancelDeviceCreation"), argumentList);
}
inline QDBusPendingReply<QDBusObjectPath> CreateDevice(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("CreateDevice"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("CreateDevice"), argumentList);
}
inline QDBusPendingReply<QDBusObjectPath> CreatePairedDevice(const QString &in0, const QDBusObjectPath &in1, const QString &in2)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2);
- return asyncCallWithArgumentList(QLatin1String("CreatePairedDevice"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2);
+ return asyncCallWithArgumentList(QStringLiteral("CreatePairedDevice"), argumentList);
}
inline QDBusPendingReply<QDBusObjectPath> FindDevice(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("FindDevice"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("FindDevice"), argumentList);
}
inline QDBusPendingReply<QVariantMap> GetProperties()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList);
}
inline QDBusPendingReply<QList<QDBusObjectPath> > ListDevices()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ListDevices"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ListDevices"), argumentList);
}
inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0, const QString &in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("RegisterAgent"), argumentList);
}
inline QDBusPendingReply<> ReleaseMode()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ReleaseMode"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ReleaseMode"), argumentList);
}
inline QDBusPendingReply<> ReleaseSession()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ReleaseSession"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ReleaseSession"), argumentList);
}
inline QDBusPendingReply<> RemoveDevice(const QDBusObjectPath &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("RemoveDevice"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("RemoveDevice"), argumentList);
}
inline QDBusPendingReply<> RequestMode(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("RequestMode"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("RequestMode"), argumentList);
}
inline QDBusPendingReply<> RequestSession()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("RequestSession"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("RequestSession"), argumentList);
}
inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("SetProperty"), argumentList);
}
inline QDBusPendingReply<> StartDiscovery()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("StartDiscovery"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("StartDiscovery"), argumentList);
}
inline QDBusPendingReply<> StopDiscovery()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("StopDiscovery"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("StopDiscovery"), argumentList);
}
inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("UnregisterAgent"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/agent.cpp b/src/bluetooth/bluez/agent.cpp
index 89840531..6fa80176 100644
--- a/src/bluetooth/bluez/agent.cpp
+++ b/src/bluetooth/bluez/agent.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
diff --git a/src/bluetooth/bluez/agent_p.h b/src/bluetooth/bluez/agent_p.h
index 8329089f..32efa62e 100644
--- a/src/bluetooth/bluez/agent_p.h
+++ b/src/bluetooth/bluez/agent_p.h
@@ -1,20 +1,19 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
-#ifndef AGENT_P_H_1291941396
-#define AGENT_P_H_1291941396
+#ifndef AGENT_P_H
+#define AGENT_P_H
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
-
QT_BEGIN_NAMESPACE
class QByteArray;
template<class T> class QList;
diff --git a/src/bluetooth/bluez/bluetoothmanagement.cpp b/src/bluetooth/bluez/bluetoothmanagement.cpp
index 9df74b34..3f97f75c 100644
--- a/src/bluetooth/bluez/bluetoothmanagement.cpp
+++ b/src/bluetooth/bluez/bluetoothmanagement.cpp
@@ -43,7 +43,7 @@
#include "bluetoothmanagement_p.h"
#include "bluez_data_p.h"
-#include "../qbluetoothsocket_p.h"
+#include "../qbluetoothsocketbase_p.h"
#include <unistd.h>
#include <sys/prctl.h>
diff --git a/src/bluetooth/bluez/bluez.pri b/src/bluetooth/bluez/bluez.pri
index b99f2712..a8ca8e22 100644
--- a/src/bluetooth/bluez/bluez.pri
+++ b/src/bluetooth/bluez/bluez.pri
@@ -17,6 +17,9 @@ HEADERS += bluez/manager_p.h \
bluez/obex_client1_bluez5_p.h \
bluez/obex_objectpush1_bluez5_p.h \
bluez/obex_transfer1_bluez5_p.h \
+ bluez/gattchar1_p.h \
+ bluez/gattdesc1_p.h \
+ bluez/gattservice1_p.h \
bluez/bluez_data_p.h \
bluez/hcimanager_p.h \
bluez/remotedevicemanager_p.h \
@@ -41,6 +44,9 @@ SOURCES += bluez/manager.cpp \
bluez/obex_client1_bluez5.cpp \
bluez/obex_objectpush1_bluez5.cpp \
bluez/obex_transfer1_bluez5.cpp \
+ bluez/gattchar1.cpp \
+ bluez/gattdesc1.cpp \
+ bluez/gattservice1.cpp \
bluez/hcimanager.cpp \
bluez/remotedevicemanager.cpp \
bluez/bluetoothmanagement.cpp
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index de41003f..f798088e 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -40,7 +40,10 @@
#include <QtCore/QGlobalStatic>
#include <QtCore/QLoggingCategory>
#include <QtCore/QMap>
+#include <QtCore/QVersionNumber>
+#include <QtNetwork/private/qnet_unix_p.h>
#include "bluez5_helper_p.h"
+#include "bluez_data_p.h"
#include "objectmanager_p.h"
#include "properties_p.h"
#include "adapter1_bluez5_p.h"
@@ -59,6 +62,7 @@ typedef enum Bluez5TestResultType
} Bluez5TestResult;
Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (BluezVersionUnknown));
+Q_GLOBAL_STATIC_WITH_ARGS(QVersionNumber, bluezDaemonVersion, (QVersionNumber()));
bool isBluez5()
{
@@ -97,6 +101,184 @@ bool isBluez5()
return (*bluezVersion() == BluezVersion5);
}
+/*
+ Checks that the mandatory Bluetooth HCI ioctls are offered
+ by Linux kernel. Returns \c true if the ictls are available; otherwise \c false.
+
+ Mandatory ioctls:
+ - HCIGETCONNLIST
+ - HCIGETDEVINFO
+ - HCIGETDEVLIST
+ */
+bool mandatoryHciIoctlsAvailable()
+{
+ // open hci socket
+ int hciSocket = ::qt_safe_socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (hciSocket < 0) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot open HCI socket:" << qt_error_string(errno);
+ return false;
+ }
+
+ // check HCIGETDEVLIST & HCIGETDEVLIST
+ struct hci_dev_req *devRequest = 0;
+ struct hci_dev_list_req *devRequestList = 0;
+ struct hci_dev_info devInfo;
+ const int devListSize = sizeof(struct hci_dev_list_req)
+ + HCI_MAX_DEV * sizeof(struct hci_dev_req);
+
+ devRequestList = (hci_dev_list_req *) malloc(devListSize);
+ if (!devRequestList) {
+ qt_safe_close(hciSocket);
+ return false; // if we cannot malloc nothing will help anyway
+ }
+
+ QScopedPointer<hci_dev_list_req, QScopedPointerPodDeleter> pDevList(devRequestList);
+ memset(pDevList.data(), 0, devListSize);
+ pDevList->dev_num = HCI_MAX_DEV;
+ devRequest = pDevList->dev_req;
+
+ if (qt_safe_ioctl(hciSocket, HCIGETDEVLIST, devRequestList) < 0) {
+ qt_safe_close(hciSocket);
+ qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVLIST:" << qt_error_string(errno);
+ return false;
+ }
+
+ if (devRequestList->dev_num > 0) {
+ devInfo.dev_id = devRequest->dev_id;
+ if (qt_safe_ioctl(hciSocket, HCIGETDEVINFO, &devInfo) < 0) {
+ qt_safe_close(hciSocket);
+ qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVINFO:" << qt_error_string(errno);
+ return false;
+ }
+ }
+
+ // check HCIGETCONNLIST
+ const int maxNoOfConnections = 20;
+ hci_conn_list_req *infoList = nullptr;
+ infoList = (hci_conn_list_req *)
+ malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info));
+
+ if (!infoList) {
+ qt_safe_close(hciSocket);
+ return false;
+ }
+
+ QScopedPointer<hci_conn_list_req, QScopedPointerPodDeleter> pInfoList(infoList);
+ pInfoList->conn_num = maxNoOfConnections;
+ pInfoList->dev_id = devInfo.dev_id;
+
+ if (qt_safe_ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) {
+ qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETCONNLIST:" << qt_error_string(errno);
+ qt_safe_close(hciSocket);
+ return false;
+ }
+
+ qt_safe_close(hciSocket);
+ return true;
+}
+
+/*!
+ * This function returns the version of bluetoothd in use on the system.
+ * This is required to determine which QLEControllerPrivate implementation
+ * is required. The following version tags are of significance:
+ *
+ * Version < 4.0 -> QLEControllerPrivateCommon
+ * Version < 5.42 -> QLEControllerPrivateBluez
+ * Version >= 5.42 -> QLEControllerPrivateBluezDBus
+ *
+ * This function utilizes a singleton pattern. It always returns a cached
+ * version tag which is determined on first call. This is necessary to
+ * avoid continuesly running the somewhat expensive tests.
+ *
+ * The function must never return a null QVersionNumber.
+ */
+QVersionNumber bluetoothdVersion()
+{
+ if (bluezDaemonVersion()->isNull()) {
+ qCDebug(QT_BT_BLUEZ) << "Detecting bluetoothd version";
+ //Order of matching
+ // 1. Pick whatever the user decides via BLUETOOTH_FORCE_DBUS_LE_VERSION
+ // Set version to below version 5.42 to use custom/old GATT stack implementation
+ const QString version = qEnvironmentVariable("BLUETOOTH_FORCE_DBUS_LE_VERSION");
+ if (!version.isNull()) {
+ const QVersionNumber vn = QVersionNumber::fromString(version);
+ if (!vn.isNull()) {
+ *bluezDaemonVersion() = vn;
+ qCDebug(QT_BT_BLUEZ) << "Forcing Bluez LE API selection:"
+ << bluezDaemonVersion()->toString();
+ }
+ }
+
+ // 2. Find bluetoothd binary and check "bluetoothd --version"
+ if (bluezDaemonVersion()->isNull() && qt_haveLinuxProcfs()) {
+ QDBusConnection session = QDBusConnection::systemBus();
+ qint64 pid = session.interface()->servicePid(QStringLiteral("org.bluez")).value();
+ QByteArray buffer;
+
+ auto determineBinaryVersion = [](const QString &binary) -> QVersionNumber {
+ QProcess process;
+ process.start(binary, {QStringLiteral("--version")});
+ process.waitForFinished();
+
+ const QString version = QString::fromLocal8Bit(process.readAll());
+ const QVersionNumber vn = QVersionNumber::fromString(version);
+ if (!vn.isNull())
+ qCDebug(QT_BT_BLUEZ) << "Detected bluetoothd version" << vn;
+ return vn;
+ };
+
+ //try reading /proc/<pid>/exe first -> requires process owner
+ qCDebug(QT_BT_BLUEZ) << "Using /proc/<pid>/exe";
+ const QString procExe = QStringLiteral("/proc/%1/exe").arg(pid);
+ const QVersionNumber vn = determineBinaryVersion(procExe);
+ if (!vn.isNull())
+ *bluezDaemonVersion() = vn;
+
+ if (bluezDaemonVersion()->isNull()) {
+ qCDebug(QT_BT_BLUEZ) << "Using /proc/<pid>/cmdline";
+ //try to reading /proc/<pid>/cmdline (does not require additional process rights)
+ QFile procFile(QStringLiteral("/proc/%1/cmdline").arg(pid));
+ if (procFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ buffer = procFile.readAll();
+ procFile.close();
+
+ // cmdline params separated by character \0 -> first is bluetoothd binary
+ const QString binary = QString::fromLocal8Bit(buffer.split('\0').at(0));
+ QFileInfo info(binary);
+ if (info.isExecutable())
+ *bluezDaemonVersion() = determineBinaryVersion(binary);
+ else
+ qCDebug(QT_BT_BLUEZ) << "Cannot determine bluetoothd version via cmdline:"
+ << binary;
+ }
+ }
+ }
+
+ // 3. Fall back to custom ATT backend, if possible?
+ if (bluezDaemonVersion()->isNull()) {
+ // Check mandatory HCI ioctls are available
+ if (mandatoryHciIoctlsAvailable()) {
+ // default 4.0 for now -> implies custom (G)ATT implementation
+ *bluezDaemonVersion() = QVersionNumber(4, 0);
+ }
+ }
+
+ // 4. Ultimate fallback -> enable dummy backend
+ if (bluezDaemonVersion()->isNull()) {
+ // version 3 represents disabled BTLE
+ // bluezDaemonVersion should not be null to avoid repeated version tests
+ *bluezDaemonVersion() = QVersionNumber(3, 0);
+ qCWarning(QT_BT_BLUEZ) << "Cannot determine bluetoothd version and required Bluetooth HCI ioctols";
+ qCWarning(QT_BT_BLUEZ) << "Disabling Qt Bluetooth LE feature";
+ }
+
+ qCDebug(QT_BT_BLUEZ) << "Bluetoothd:" << bluezDaemonVersion()->toString();
+ }
+
+ Q_ASSERT(!bluezDaemonVersion()->isNull());
+ return *bluezDaemonVersion();
+}
+
struct AdapterData
{
public:
diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h
index 2d72caf1..1747f249 100644
--- a/src/bluetooth/bluez/bluez5_helper_p.h
+++ b/src/bluetooth/bluez/bluez5_helper_p.h
@@ -54,6 +54,7 @@
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
#include <QtBluetooth/QBluetoothAddress>
+#include <QtBluetooth/private/qtbluetoothglobal_p.h>
typedef QMap<QString, QVariantMap> InterfaceList;
typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;
@@ -67,6 +68,9 @@ QT_BEGIN_NAMESPACE
bool isBluez5();
+// exported for unit test purposes
+Q_BLUETOOTH_PRIVATE_EXPORT QVersionNumber bluetoothdVersion();
+
QString sanitizeNameForDBus(const QString& text);
QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok);
diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h
index 684cd5b8..2a2e597c 100644
--- a/src/bluetooth/bluez/bluez_data_p.h
+++ b/src/bluetooth/bluez/bluez_data_p.h
@@ -123,6 +123,10 @@ struct bt_security {
#error "Unknown byte order"
#endif
+#define HCIGETCONNLIST _IOR('H', 212, int)
+#define HCIGETDEVINFO _IOR('H', 211, int)
+#define HCIGETDEVLIST _IOR('H', 210, int)
+
// Bluetooth address
typedef struct {
quint8 b[6];
diff --git a/src/bluetooth/bluez/device.cpp b/src/bluetooth/bluez/device.cpp
index 5dc814dc..14b91ad0 100644
--- a/src/bluetooth/bluez/device.cpp
+++ b/src/bluetooth/bluez/device.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/device1_bluez5.cpp b/src/bluetooth/bluez/device1_bluez5.cpp
index 491a365d..cd6453ad 100644
--- a/src/bluetooth/bluez/device1_bluez5.cpp
+++ b/src/bluetooth/bluez/device1_bluez5.cpp
@@ -1,5 +1,6 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml
*
* qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
diff --git a/src/bluetooth/bluez/device1_bluez5_p.h b/src/bluetooth/bluez/device1_bluez5_p.h
index 4feb5318..b9523a56 100644
--- a/src/bluetooth/bluez/device1_bluez5_p.h
+++ b/src/bluetooth/bluez/device1_bluez5_p.h
@@ -1,5 +1,6 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml
*
* qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
diff --git a/src/bluetooth/bluez/device_p.h b/src/bluetooth/bluez/device_p.h
index 417db3d9..2e1e39ad 100644
--- a/src/bluetooth/bluez/device_p.h
+++ b/src/bluetooth/bluez/device_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef DEVICE_P_H_1273205927
-#define DEVICE_P_H_1273205927
+#ifndef DEVICE_P_H
+#define DEVICE_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -32,7 +32,7 @@ public:
{ return "org.bluez.Device"; }
public:
- OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezDeviceInterface();
@@ -40,53 +40,53 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CancelDiscovery()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("CancelDiscovery"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("CancelDiscovery"), argumentList);
}
inline QDBusPendingReply<QDBusObjectPath> CreateNode(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("CreateNode"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("CreateNode"), argumentList);
}
inline QDBusPendingReply<> Disconnect()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Disconnect"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Disconnect"), argumentList);
}
inline QDBusPendingReply<ServiceMap> DiscoverServices(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("DiscoverServices"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("DiscoverServices"), argumentList);
}
inline QDBusPendingReply<QVariantMap> GetProperties()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList);
}
inline QDBusPendingReply<QList<QDBusObjectPath> > ListNodes()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ListNodes"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ListNodes"), argumentList);
}
inline QDBusPendingReply<> RemoveNode(const QDBusObjectPath &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("RemoveNode"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("RemoveNode"), argumentList);
}
inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("SetProperty"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/gattchar1.cpp b/src/bluetooth/bluez/gattchar1.cpp
new file mode 100644
index 00000000..cdb3fc0d
--- /dev/null
+++ b/src/bluetooth/bluez/gattchar1.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "gattchar1_p.h"
+
+/*
+ * Implementation of interface class OrgBluezGattCharacteristic1Interface
+ */
+
+OrgBluezGattCharacteristic1Interface::OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezGattCharacteristic1Interface::~OrgBluezGattCharacteristic1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/gattchar1_p.h b/src/bluetooth/bluez/gattchar1_p.h
new file mode 100644
index 00000000..c19e9f58
--- /dev/null
+++ b/src/bluetooth/bluez/gattchar1_p.h
@@ -0,0 +1,93 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef GATTCHAR1_P_H
+#define GATTCHAR1_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.GattCharacteristic1
+ */
+class OrgBluezGattCharacteristic1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.GattCharacteristic1"; }
+
+public:
+ OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
+
+ ~OrgBluezGattCharacteristic1Interface();
+
+ Q_PROPERTY(QStringList Flags READ flags)
+ inline QStringList flags() const
+ { return qvariant_cast< QStringList >(property("Flags")); }
+
+ Q_PROPERTY(bool Notifying READ notifying)
+ inline bool notifying() const
+ { return qvariant_cast< bool >(property("Notifying")); }
+
+ Q_PROPERTY(QDBusObjectPath Service READ service)
+ inline QDBusObjectPath service() const
+ { return qvariant_cast< QDBusObjectPath >(property("Service")); }
+
+ Q_PROPERTY(QString UUID READ uUID)
+ inline QString uUID() const
+ { return qvariant_cast< QString >(property("UUID")); }
+
+ Q_PROPERTY(QByteArray Value READ value)
+ inline QByteArray value() const
+ { return qvariant_cast< QByteArray >(property("Value")); }
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<QByteArray> ReadValue(const QVariantMap &options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(options);
+ return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList);
+ }
+
+ inline QDBusPendingReply<> StartNotify()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QStringLiteral("StartNotify"), argumentList);
+ }
+
+ inline QDBusPendingReply<> StopNotify()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QStringLiteral("StopNotify"), argumentList);
+ }
+
+ inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(value) << QVariant::fromValue(options);
+ return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList);
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ typedef ::OrgBluezGattCharacteristic1Interface GattCharacteristic1;
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/gattdesc1.cpp b/src/bluetooth/bluez/gattdesc1.cpp
new file mode 100644
index 00000000..8447e49b
--- /dev/null
+++ b/src/bluetooth/bluez/gattdesc1.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "gattdesc1_p.h"
+
+/*
+ * Implementation of interface class OrgBluezGattDescriptor1Interface
+ */
+
+OrgBluezGattDescriptor1Interface::OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezGattDescriptor1Interface::~OrgBluezGattDescriptor1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/gattdesc1_p.h b/src/bluetooth/bluez/gattdesc1_p.h
new file mode 100644
index 00000000..6ade7a42
--- /dev/null
+++ b/src/bluetooth/bluez/gattdesc1_p.h
@@ -0,0 +1,73 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef GATTDESC1_P_H
+#define GATTDESC1_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.GattDescriptor1
+ */
+class OrgBluezGattDescriptor1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.GattDescriptor1"; }
+
+public:
+ OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
+
+ ~OrgBluezGattDescriptor1Interface();
+
+ Q_PROPERTY(QDBusObjectPath Characteristic READ characteristic)
+ inline QDBusObjectPath characteristic() const
+ { return qvariant_cast< QDBusObjectPath >(property("Characteristic")); }
+
+ Q_PROPERTY(QString UUID READ uUID)
+ inline QString uUID() const
+ { return qvariant_cast< QString >(property("UUID")); }
+
+ Q_PROPERTY(QByteArray Value READ value)
+ inline QByteArray value() const
+ { return qvariant_cast< QByteArray >(property("Value")); }
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<QByteArray> ReadValue(const QVariantMap &options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(options);
+ return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList);
+ }
+
+ inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(value) << QVariant::fromValue(options);
+ return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList);
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ typedef ::OrgBluezGattDescriptor1Interface GattDescriptor1;
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/gattservice1.cpp b/src/bluetooth/bluez/gattservice1.cpp
new file mode 100644
index 00000000..0b80ac90
--- /dev/null
+++ b/src/bluetooth/bluez/gattservice1.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "gattservice1_p.h"
+
+/*
+ * Implementation of interface class OrgBluezGattService1Interface
+ */
+
+OrgBluezGattService1Interface::OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezGattService1Interface::~OrgBluezGattService1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/gattservice1_p.h b/src/bluetooth/bluez/gattservice1_p.h
new file mode 100644
index 00000000..128305f1
--- /dev/null
+++ b/src/bluetooth/bluez/gattservice1_p.h
@@ -0,0 +1,63 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef GATTSERVICE1_P_H
+#define GATTSERVICE1_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.GattService1
+ */
+class OrgBluezGattService1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.GattService1"; }
+
+public:
+ OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
+
+ ~OrgBluezGattService1Interface();
+
+ Q_PROPERTY(QDBusObjectPath Device READ device)
+ inline QDBusObjectPath device() const
+ { return qvariant_cast< QDBusObjectPath >(property("Device")); }
+
+ Q_PROPERTY(QList<QDBusObjectPath> Includes READ includes)
+ inline QList<QDBusObjectPath> includes() const
+ { return qvariant_cast< QList<QDBusObjectPath> >(property("Includes")); }
+
+ Q_PROPERTY(bool Primary READ primary)
+ inline bool primary() const
+ { return qvariant_cast< bool >(property("Primary")); }
+
+ Q_PROPERTY(QString UUID READ uUID)
+ inline QString uUID() const
+ { return qvariant_cast< QString >(property("UUID")); }
+
+public Q_SLOTS: // METHODS
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ typedef ::OrgBluezGattService1Interface GattService1;
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/generate b/src/bluetooth/bluez/generate
index cdba18c4..5c401ffe 100755
--- a/src/bluetooth/bluez/generate
+++ b/src/bluetooth/bluez/generate
@@ -13,10 +13,14 @@ qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobe
#Bluez 5
qdbusxml2cpp -p adapter1_bluez5_p.h:adapter1_bluez5.cpp org.bluez.Adapter1.xml
-qdbusxml2cpp -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml
+qdbusxml2cpp -i bluez5_helper_p.h -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml
qdbusxml2cpp -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml
-qdbusxml2cpp -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml
+qdbusxml2cpp -i bluez5_helper_p.h -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml
qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml
qdbusxml2cpp -p obex_client1_bluez5_p.h:obex_client1_bluez5_p.h org.bluez.Client1.xml
qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml
qdbusxml2cpp -p obex_transfer1_bluez5_p.h:obex_transfer1_bluez5_p.h org.bluez.obex.Transfer1.xml
+qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml
+qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml
+qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml
+
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index c524117c..bdb74ae0 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -40,7 +40,7 @@
#include "hcimanager_p.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocketbase_p.h"
#include "qlowenergyconnectionparameters.h"
#include <QtCore/qloggingcategory.h>
@@ -53,10 +53,6 @@
#include <sys/uio.h>
#include <unistd.h>
-#define HCIGETCONNLIST _IOR('H', 212, int)
-#define HCIGETDEVINFO _IOR('H', 211, int)
-#define HCIGETDEVLIST _IOR('H', 210, int)
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
diff --git a/src/bluetooth/bluez/manager.cpp b/src/bluetooth/bluez/manager.cpp
index b5d6590d..8ca6fb42 100644
--- a/src/bluetooth/bluez/manager.cpp
+++ b/src/bluetooth/bluez/manager.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/manager_p.h b/src/bluetooth/bluez/manager_p.h
index edb1c73b..a969e067 100644
--- a/src/bluetooth/bluez/manager_p.h
+++ b/src/bluetooth/bluez/manager_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef MANAGER_P_H_1273205927
-#define MANAGER_P_H_1273205927
+#ifndef MANAGER_P_H
+#define MANAGER_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.Manager"; }
public:
- OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezManagerInterface();
@@ -39,20 +39,20 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<QDBusObjectPath> DefaultAdapter()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("DefaultAdapter"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("DefaultAdapter"), argumentList);
}
inline QDBusPendingReply<QDBusObjectPath> FindAdapter(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("FindAdapter"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("FindAdapter"), argumentList);
}
inline QDBusPendingReply<QList<QDBusObjectPath> > ListAdapters()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ListAdapters"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ListAdapters"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/obex_agent.cpp b/src/bluetooth/bluez/obex_agent.cpp
index c5252898..5bc05f87 100644
--- a/src/bluetooth/bluez/obex_agent.cpp
+++ b/src/bluetooth/bluez/obex_agent.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
- * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
diff --git a/src/bluetooth/bluez/obex_agent_p.h b/src/bluetooth/bluez/obex_agent_p.h
index 8af38d86..242b2598 100644
--- a/src/bluetooth/bluez/obex_agent_p.h
+++ b/src/bluetooth/bluez/obex_agent_p.h
@@ -1,20 +1,19 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
- * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
-#ifndef OBEX_AGENT_P_H_1291359033
-#define OBEX_AGENT_P_H_1291359033
+#ifndef OBEX_AGENT_P_H
+#define OBEX_AGENT_P_H
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
-
QT_BEGIN_NAMESPACE
class QByteArray;
template<class T> class QList;
diff --git a/src/bluetooth/bluez/obex_client.cpp b/src/bluetooth/bluez/obex_client.cpp
index 07730d42..bef9155a 100644
--- a/src/bluetooth/bluez/obex_client.cpp
+++ b/src/bluetooth/bluez/obex_client.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/obex_client1_bluez5_p.h b/src/bluetooth/bluez/obex_client1_bluez5_p.h
index 5133faea..ccd5b0d6 100644
--- a/src/bluetooth/bluez/obex_client1_bluez5_p.h
+++ b/src/bluetooth/bluez/obex_client1_bluez5_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp org.bluez.Client1.xml -p asd
+ * Command line was: qdbusxml2cpp -p obex_client1_bluez5_p.h:obex_client1_bluez5_p.h org.bluez.Client1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef ASD_H_1399976174
-#define ASD_H_1399976174
+#ifndef OBEX_CLIENT1_BLUEZ5_P_H
+#define OBEX_CLIENT1_BLUEZ5_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.obex.Client1"; }
public:
- OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezObexClient1Interface();
@@ -40,14 +40,14 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(destination) << QVariant::fromValue(args);
- return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("CreateSession"), argumentList);
}
inline QDBusPendingReply<> RemoveSession(const QDBusObjectPath &session)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(session);
- return asyncCallWithArgumentList(QLatin1String("RemoveSession"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("RemoveSession"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/obex_client_p.h b/src/bluetooth/bluez/obex_client_p.h
index b2dd0f61..13b638b6 100644
--- a/src/bluetooth/bluez/obex_client_p.h
+++ b/src/bluetooth/bluez/obex_client_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBEX_CLIENT_P_H_1291349694
-#define OBEX_CLIENT_P_H_1291349694
+#ifndef OBEX_CLIENT_P_H
+#define OBEX_CLIENT_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.openobex.Client"; }
public:
- OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgOpenobexClientInterface();
@@ -39,36 +39,36 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<QDBusObjectPath> CreateSession(const QVariantMap &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("CreateSession"), argumentList);
}
inline QDBusPendingReply<> ExchangeBusinessCards(const QVariantMap &in0, const QString &in1, const QString &in2)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2);
- return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2);
+ return asyncCallWithArgumentList(QStringLiteral("ExchangeBusinessCards"), argumentList);
}
inline QDBusPendingReply<QString> GetCapabilities(const QVariantMap &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("GetCapabilities"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("GetCapabilities"), argumentList);
}
inline QDBusPendingReply<> PullBusinessCard(const QVariantMap &in0, const QString &in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("PullBusinessCard"), argumentList);
}
inline QDBusPendingReply<> SendFiles(const QVariantMap &in0, const QStringList &in1, const QDBusObjectPath &in2)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2);
- return asyncCallWithArgumentList(QLatin1String("SendFiles"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2);
+ return asyncCallWithArgumentList(QStringLiteral("SendFiles"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/obex_manager.cpp b/src/bluetooth/bluez/obex_manager.cpp
index 0eb5d1c8..cc6e0ecb 100644
--- a/src/bluetooth/bluez/obex_manager.cpp
+++ b/src/bluetooth/bluez/obex_manager.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/obex_manager_p.h b/src/bluetooth/bluez/obex_manager_p.h
index a6e4d189..822954ab 100644
--- a/src/bluetooth/bluez/obex_manager_p.h
+++ b/src/bluetooth/bluez/obex_manager_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBEX_MANAGER_P_H_1291186314
-#define OBEX_MANAGER_P_H_1291186314
+#ifndef OBEX_MANAGER_P_H
+#define OBEX_MANAGER_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.openobex.Manager"; }
public:
- OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgOpenobexManagerInterface();
@@ -39,15 +39,15 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("RegisterAgent"), argumentList);
}
inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("UnregisterAgent"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp
index 6edb27a8..59b94e80 100644
--- a/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp
+++ b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp
@@ -1,8 +1,8 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5
+ * Command line was: qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h
index ba5f090d..5fa1703b 100644
--- a/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h
+++ b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5
+ * Command line was: qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318
-#define OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318
+#ifndef OBEX_OBJECTPUSH1_BLUEZ5_P_H
+#define OBEX_OBJECTPUSH1_BLUEZ5_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.obex.ObjectPush1"; }
public:
- OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezObexObjectPush1Interface();
@@ -40,13 +40,13 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile);
- return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ExchangeBusinessCards"), argumentList);
}
inline QDBusReply<QDBusObjectPath> ExchangeBusinessCards(const QString &clientfile, const QString &targetfile, QVariantMap &properties)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile);
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("ExchangeBusinessCards"), argumentList);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("ExchangeBusinessCards"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
}
@@ -57,13 +57,13 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(targetfile);
- return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("PullBusinessCard"), argumentList);
}
inline QDBusReply<QDBusObjectPath> PullBusinessCard(const QString &targetfile, QVariantMap &properties)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(targetfile);
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("PullBusinessCard"), argumentList);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("PullBusinessCard"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
}
@@ -74,13 +74,13 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(sourcefile);
- return asyncCallWithArgumentList(QLatin1String("SendFile"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("SendFile"), argumentList);
}
inline QDBusReply<QDBusObjectPath> SendFile(const QString &sourcefile, QVariantMap &properties)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(sourcefile);
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("SendFile"), argumentList);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("SendFile"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
}
diff --git a/src/bluetooth/bluez/obex_transfer.cpp b/src/bluetooth/bluez/obex_transfer.cpp
index 49e1f7c9..be27362f 100644
--- a/src/bluetooth/bluez/obex_transfer.cpp
+++ b/src/bluetooth/bluez/obex_transfer.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/obex_transfer1_bluez5_p.h b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h
index 2307f2ae..ccde588e 100644
--- a/src/bluetooth/bluez/obex_transfer1_bluez5_p.h
+++ b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp org.bluez.obex.Transfer1.xml -p obex_transfer1_bluez5
+ * Command line was: qdbusxml2cpp -p obex_transfer1_bluez5_p.h:obex_transfer1_bluez5_p.h org.bluez.obex.Transfer1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBEX_TRANSFER1_BLUEZ5_H_1400058158
-#define OBEX_TRANSFER1_BLUEZ5_H_1400058158
+#ifndef OBEX_TRANSFER1_BLUEZ5_P_H
+#define OBEX_TRANSFER1_BLUEZ5_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.obex.Transfer1"; }
public:
- OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezObexTransfer1Interface();
@@ -63,19 +63,19 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> Cancel()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Cancel"), argumentList);
}
inline QDBusPendingReply<> Resume()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Resume"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Resume"), argumentList);
}
inline QDBusPendingReply<> Suspend()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Suspend"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Suspend"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/obex_transfer_p.h b/src/bluetooth/bluez/obex_transfer_p.h
index 81b9eb22..b8fa0a5d 100644
--- a/src/bluetooth/bluez/obex_transfer_p.h
+++ b/src/bluetooth/bluez/obex_transfer_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBEX_TRANSFER_P_H_1291853849
-#define OBEX_TRANSFER_P_H_1291853849
+#ifndef OBEX_TRANSFER_P_H
+#define OBEX_TRANSFER_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.openobex.Transfer"; }
public:
- OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgOpenobexTransferInterface();
@@ -39,13 +39,13 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> Cancel()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Cancel"), argumentList);
}
inline QDBusPendingReply<QVariantMap> GetProperties()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/objectmanager.cpp b/src/bluetooth/bluez/objectmanager.cpp
index a8e8fdba..4484ea27 100644
--- a/src/bluetooth/bluez/objectmanager.cpp
+++ b/src/bluetooth/bluez/objectmanager.cpp
@@ -1,8 +1,8 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p objectmanager -v -i bluez5_helper.h org.freedesktop.dbus.objectmanager.xml
+ * Command line was: qdbusxml2cpp -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/objectmanager_p.h b/src/bluetooth/bluez/objectmanager_p.h
index 74f5ab43..7aa2f35b 100644
--- a/src/bluetooth/bluez/objectmanager_p.h
+++ b/src/bluetooth/bluez/objectmanager_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p objectmanager -v -i bluez5_helper.h org.freedesktop.dbus.objectmanager.xml
+ * Command line was: qdbusxml2cpp -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef OBJECTMANAGER_H_1396883000
-#define OBJECTMANAGER_H_1396883000
+#ifndef OBJECTMANAGER_P_H
+#define OBJECTMANAGER_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -33,7 +33,7 @@ public:
{ return "org.freedesktop.DBus.ObjectManager"; }
public:
- OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgFreedesktopDBusObjectManagerInterface();
@@ -41,7 +41,7 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<ManagedObjectList> GetManagedObjects()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("GetManagedObjects"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("GetManagedObjects"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml
new file mode 100644
index 00000000..f62014cf
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.GattCharacteristic1">
+ <method name="ReadValue">
+ <arg name="options" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+ <arg name="value" type="ay" direction="out"/>
+ </method>
+ <method name="WriteValue">
+ <arg name="value" type="ay" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ </method>
+ <method name="StartNotify"></method>
+ <method name="StopNotify"></method>
+ <property name="UUID" type="s" access="read"></property>
+ <property name="Service" type="o" access="read"></property>
+ <property name="Value" type="ay" access="read"></property>
+ <property name="Notifying" type="b" access="read"></property>
+ <property name="Flags" type="as" access="read"></property>
+ </interface>
+</node>
diff --git a/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml
new file mode 100644
index 00000000..fc7ebce0
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.GattDescriptor1">
+ <method name="ReadValue">
+ <arg name="options" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+ <arg name="value" type="ay" direction="out"/>
+ </method>
+ <method name="WriteValue">
+ <arg name="value" type="ay" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ </method>
+ <property name="UUID" type="s" access="read"></property>
+ <property name="Characteristic" type="o" access="read"></property>
+ <property name="Value" type="ay" access="read"></property>
+ </interface>
+</node>
diff --git a/src/bluetooth/bluez/org.bluez.GattService1.xml b/src/bluetooth/bluez/org.bluez.GattService1.xml
new file mode 100644
index 00000000..e90eeda7
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.GattService1.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.GattService1">
+ <property name="UUID" type="s" access="read"></property>
+ <property name="Device" type="o" access="read"></property>
+ <property name="Primary" type="b" access="read"></property>
+ <property name="Includes" type="ao" access="read"></property>
+ </interface>
+</node>
diff --git a/src/bluetooth/bluez/profile1.cpp b/src/bluetooth/bluez/profile1.cpp
index c289c89b..26d42c7c 100644
--- a/src/bluetooth/bluez/profile1.cpp
+++ b/src/bluetooth/bluez/profile1.cpp
@@ -1,8 +1,8 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml
+ * Command line was: qdbusxml2cpp -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/profile1_p.h b/src/bluetooth/bluez/profile1_p.h
index a08f10e0..e61fb2a9 100644
--- a/src/bluetooth/bluez/profile1_p.h
+++ b/src/bluetooth/bluez/profile1_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml
+ * Command line was: qdbusxml2cpp -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef PROFILE1_H_1400142085
-#define PROFILE1_H_1400142085
+#ifndef PROFILE1_P_H
+#define PROFILE1_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.ProfileManager1"; }
public:
- OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezProfileManager1Interface();
@@ -40,14 +40,14 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(profile) << QVariant::fromValue(UUID) << QVariant::fromValue(options);
- return asyncCallWithArgumentList(QLatin1String("RegisterProfile"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("RegisterProfile"), argumentList);
}
inline QDBusPendingReply<> UnregisterProfile(const QDBusObjectPath &profile)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(profile);
- return asyncCallWithArgumentList(QLatin1String("UnregisterProfile"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("UnregisterProfile"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/properties.cpp b/src/bluetooth/bluez/properties.cpp
index 4ddbc30c..1c10bfdc 100644
--- a/src/bluetooth/bluez/properties.cpp
+++ b/src/bluetooth/bluez/properties.cpp
@@ -1,8 +1,8 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p properties -v org.freedesktop.dbus.properties.xml
+ * Command line was: qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/properties_p.h b/src/bluetooth/bluez/properties_p.h
index daadfefc..16a43e80 100644
--- a/src/bluetooth/bluez/properties_p.h
+++ b/src/bluetooth/bluez/properties_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p properties -v org.freedesktop.dbus.properties.xml
+ * Command line was: qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml
*
- * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef PROPERTIES_H_1396952220
-#define PROPERTIES_H_1396952220
+#ifndef PROPERTIES_P_H
+#define PROPERTIES_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.freedesktop.DBus.Properties"; }
public:
- OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgFreedesktopDBusPropertiesInterface();
@@ -40,21 +40,21 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name);
- return asyncCallWithArgumentList(QLatin1String("Get"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Get"), argumentList);
}
inline QDBusPendingReply<QVariantMap> GetAll(const QString &interface)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(interface);
- return asyncCallWithArgumentList(QLatin1String("GetAll"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("GetAll"), argumentList);
}
inline QDBusPendingReply<> Set(const QString &interface, const QString &name, const QDBusVariant &value)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name) << QVariant::fromValue(value);
- return asyncCallWithArgumentList(QLatin1String("Set"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Set"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/remotedevicemanager.cpp b/src/bluetooth/bluez/remotedevicemanager.cpp
index f63b21e6..5d17d571 100644
--- a/src/bluetooth/bluez/remotedevicemanager.cpp
+++ b/src/bluetooth/bluez/remotedevicemanager.cpp
@@ -106,6 +106,7 @@ void RemoteDeviceManager::prepareNextJob()
jobQueue.pop_front();
jobInProgress = false;
+ qDebug(QT_BT_BLUEZ) << "RemoteDeviceManager job queue status:" << jobQueue.empty();
if (jobQueue.empty())
emit finished();
else
@@ -163,8 +164,10 @@ void RemoteDeviceManager::disconnectDevice(const QBluetoothAddress &remote)
}
}
- if (!jobStarted)
+ if (!jobStarted) {
+ qDebug(QT_BT_BLUEZ) << "RemoteDeviceManager JobDisconnectDevice failed";
QTimer::singleShot(0, this, [this](){ prepareNextJob(); });
+ }
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/bluez/service.cpp b/src/bluetooth/bluez/service.cpp
index 2004bea7..d2b15fc2 100644
--- a/src/bluetooth/bluez/service.cpp
+++ b/src/bluetooth/bluez/service.cpp
@@ -1,8 +1,8 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
diff --git a/src/bluetooth/bluez/service_p.h b/src/bluetooth/bluez/service_p.h
index e8c5e1f4..573265a8 100644
--- a/src/bluetooth/bluez/service_p.h
+++ b/src/bluetooth/bluez/service_p.h
@@ -1,15 +1,15 @@
/*
- * This file was generated by qdbusxml2cpp version 0.7
+ * This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service
*
- * Copyright (C) 2015 The Qt Company Ltd.
+ * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
-#ifndef SERVICE_P_H_1277421939
-#define SERVICE_P_H_1277421939
+#ifndef SERVICE_P_H
+#define SERVICE_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.Service"; }
public:
- OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezServiceInterface();
@@ -39,35 +39,35 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<uint> AddRecord(const QString &in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("AddRecord"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("AddRecord"), argumentList);
}
inline QDBusPendingReply<> CancelAuthorization()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("CancelAuthorization"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("CancelAuthorization"), argumentList);
}
inline QDBusPendingReply<> RemoveRecord(uint in0)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0);
- return asyncCallWithArgumentList(QLatin1String("RemoveRecord"), argumentList);
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QStringLiteral("RemoveRecord"), argumentList);
}
inline QDBusPendingReply<> RequestAuthorization(const QString &in0, uint in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("RequestAuthorization"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("RequestAuthorization"), argumentList);
}
inline QDBusPendingReply<> UpdateRecord(uint in0, const QString &in1)
{
QList<QVariant> argumentList;
- argumentList << qVariantFromValue(in0) << qVariantFromValue(in1);
- return asyncCallWithArgumentList(QLatin1String("UpdateRecord"), argumentList);
+ argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
+ return asyncCallWithArgumentList(QStringLiteral("UpdateRecord"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
index 1eec9206..2e28c3f5 100644
--- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
+++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.qml b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.qml
index fcafbd53..efed6cc7 100644
--- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.qml
+++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc
index 9cb5f3b2..2a4f72bc 100644
--- a/src/bluetooth/doc/src/bluetooth-index.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-index.qdoc
@@ -43,7 +43,7 @@ Currently, the API is supported on the following platforms:
\li \l {Qt for Linux/X11}{Linux (BlueZ 4.x/5.x)}
\li \l {Qt for OS X}{macOS}
\li \l {Qt for WinRT}{WinRT}
- \li \l {Qt for Windows}{Windows}
+ \li \l {Qt for Windows}{Win32}
\row
\li Classic Bluetooth
\li x
@@ -78,6 +78,11 @@ Currently, the API is supported on the following platforms:
\li
\endtable
+Despite there not being a Win32 port yet, the WinRT backend is automatically used
+if the win32 target platform supports the required WinRT APIs. Minimal requirement is Windows 10 version 1507
+with slightly improved service discovery since Windows 10 version 1607. Therefore Windows 7 and 8.x
+targets are excluded.
+
\section1 Overview
Bluetooth is a short-range (less than 100 meters) wireless technology. It
diff --git a/src/bluetooth/doc/src/bluetooth-qml.qdoc b/src/bluetooth/doc/src/bluetooth-qml.qdoc
index 51aa5a25..2f37cb9b 100644
--- a/src/bluetooth/doc/src/bluetooth-qml.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-qml.qdoc
@@ -28,7 +28,7 @@
/*!
-\qmlmodule QtBluetooth 5.2
+\qmlmodule QtBluetooth 5.11
\title Qt Bluetooth QML Types
\ingroup qmlmodules
\brief Provides QML types for basic Bluetooth operations on devices.
diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri
index 13187e4f..b7ac0535 100644
--- a/src/bluetooth/osx/osxbt.pri
+++ b/src/bluetooth/osx/osxbt.pri
@@ -1,6 +1,9 @@
SOURCES += osx/uistrings.cpp osx/osxbtnotifier.cpp
-PRIVATE_HEADERS += osx/uistrings_p.h
-//QMAKE_CXXFLAGS_WARN_ON += -Wno-nullability-completeness
+PRIVATE_HEADERS += osx/uistrings_p.h \
+ osx/osxbtgcdtimer_p.h
+
+OBJECTIVE_SOURCES += osx/osxbtgcdtimer.mm
+#QMAKE_CXXFLAGS_WARN_ON += -Wno-nullability-completeness
CONFIG(osx) {
PRIVATE_HEADERS += osx/osxbtutility_p.h \
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index 70473f1f..9254bd98 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -79,8 +79,21 @@ NSUInteger qt_countGATTEntries(CBService *service)
return n;
}
+ObjCStrongReference<NSError> qt_timeoutNSError(OperationTimeout type)
+{
+ // For now we do not provide details, since nobody is using this NSError
+ // after all (except callbacks checking if an operation was successful
+ // or not).
+ Q_ASSERT(type != OperationTimeout::none);
+ Q_UNUSED(type)
+ NSError *nsError = [[NSError alloc] initWithDomain:CBErrorDomain
+ code:CBErrorOperationCancelled
+ userInfo:nil];
+ return ObjCStrongReference<NSError>(nsError, false /*do not retain, done already*/);
}
+} // namespace OSXBluetooth
+
QT_END_NAMESPACE
@@ -115,9 +128,11 @@ QT_END_NAMESPACE
- (id)initWith:(OSXBluetooth::LECBManagerNotifier *)aNotifier
{
+ using namespace OSXBluetooth;
+
if (self = [super init]) {
manager = nil;
- managerState = OSXBluetooth::CentralManagerIdle;
+ managerState = CentralManagerIdle;
disconnectPending = false;
peripheral = nil;
notifier = aNotifier;
@@ -125,6 +140,17 @@ QT_END_NAMESPACE
lastValidHandle = 0;
requestPending = false;
currentReadHandle = 0;
+ timeoutType = OperationTimeout::none;
+
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("BLUETOOTH_GATT_TIMEOUT"))) {
+ bool ok = false;
+ const int value = qEnvironmentVariableIntValue("BLUETOOTH_GATT_TIMEOUT", &ok);
+ if (ok && value >= 0)
+ timeoutMS = value;
+ }
+
+ if (!timeoutMS)
+ timeoutMS = 20000;
}
return self;
@@ -153,6 +179,63 @@ QT_END_NAMESPACE
[super dealloc];
}
+- (void)watchAfter:(id)object timeout:(OSXBluetooth::OperationTimeout)type
+{
+ using namespace OSXBluetooth;
+
+ objectUnderWatch = object;
+ timeoutType = type;
+ [timeoutWatchdog cancelTimer];
+ timeoutWatchdog.reset([[GCDTimerObjC alloc] initWithDelegate:self]);
+ [timeoutWatchdog startWithTimeout:timeoutMS step:200];
+}
+
+- (void)stopWatchdog
+{
+ [timeoutWatchdog cancelTimer];
+ objectUnderWatch = nil;
+ timeoutType = OSXBluetooth::OperationTimeout::none;
+}
+
+- (void)timeout
+{
+ using namespace OSXBluetooth;
+
+ Q_ASSERT(objectUnderWatch);
+ NSLog(@"Timeout caused by: %@", objectUnderWatch);
+ const ObjCStrongReference<NSError> nsError(qt_timeoutNSError(timeoutType));
+ switch (timeoutType) {
+ case OperationTimeout::serviceDiscovery:
+ qCWarning(QT_BT_OSX, "Timeout in services discovery");
+ [self peripheral:peripheral didDiscoverServices:nsError];
+ break;
+ case OperationTimeout::includedServicesDiscovery:
+ qCWarning(QT_BT_OSX, "Timeout in included services discovery");
+ [self peripheral:peripheral didDiscoverIncludedServicesForService:objectUnderWatch error:nsError];
+ break;
+ case OperationTimeout::characteristicsDiscovery:
+ qCWarning(QT_BT_OSX, "Timeout in characteristics discovery");
+ [self peripheral:peripheral didDiscoverCharacteristicsForService:objectUnderWatch error:nsError];
+ break;
+ case OperationTimeout::characteristicRead:
+ qCWarning(QT_BT_OSX, "Timeout while reading a characteristic");
+ [self peripheral:peripheral didUpdateValueForCharacteristic:objectUnderWatch error:nsError];
+ break;
+ case OperationTimeout::descriptorsDiscovery:
+ qCWarning(QT_BT_OSX, "Timeout in descriptors discovery");
+ [self peripheral:peripheral didDiscoverDescriptorsForCharacteristic:objectUnderWatch error:nsError];
+ break;
+ case OperationTimeout::descriptorRead:
+ qCWarning(QT_BT_OSX, "Timeout while reading a descriptor");
+ [self peripheral:peripheral didUpdateValueForDescriptor:objectUnderWatch error:nsError];
+ break;
+ case OperationTimeout::characteristicWrite:
+ qCWarning(QT_BT_OSX, "Timeout while writing a characteristic with response");
+ [self peripheral:peripheral didWriteValueForCharacteristic:objectUnderWatch error:nsError];
+ default:;
+ }
+}
+
- (void)connectToDevice:(const QBluetoothUuid &)aDeviceUuid
{
disconnectPending = false; // Cancel the previous disconnect if any.
@@ -235,10 +318,11 @@ QT_END_NAMESPACE
- (void)connectToPeripheral
{
+ using namespace OSXBluetooth;
+
Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)");
Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
- Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
- Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state");
// The state is still the same - connecting.
if ([self isConnected]) {
@@ -247,7 +331,7 @@ QT_END_NAMESPACE
emit notifier->connected();
} else {
qCDebug(QT_BT_OSX) << "trying to connect";
- managerState = OSXBluetooth::CentralManagerConnecting;
+ managerState = CentralManagerConnecting;
[manager connectPeripheral:peripheral options:nil];
}
}
@@ -292,9 +376,10 @@ QT_END_NAMESPACE
- (void)discoverServices
{
+ using namespace OSXBluetooth;
+
Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
- Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle,
- Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state");
// From Apple's docs:
//
@@ -304,7 +389,8 @@ QT_END_NAMESPACE
//
// ... but we'd like to have them all:
[peripheral setDelegate:self];
- managerState = OSXBluetooth::CentralManagerDiscovering;
+ managerState = CentralManagerDiscovering;
+ [self watchAfter:peripheral timeout:OperationTimeout::serviceDiscovery];
[peripheral discoverServices:nil];
}
@@ -333,6 +419,7 @@ QT_END_NAMESPACE
CBService *const s = [services objectAtIndex:currentService];
[visitedServices addObject:s];
managerState = CentralManagerDiscovering;
+ [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery];
[peripheral discoverIncludedServices:nil forService:s];
}
}
@@ -359,6 +446,7 @@ QT_END_NAMESPACE
if (CBService *const service = [self serviceForUUID:serviceUuid]) {
servicesToDiscoverDetails.append(serviceUuid);
+ [self watchAfter:service timeout:OperationTimeout::characteristicsDiscovery];
[peripheral discoverCharacteristics:nil forService:service];
return;
}
@@ -366,10 +454,8 @@ QT_END_NAMESPACE
qCWarning(QT_BT_OSX) << "unknown service uuid"
<< serviceUuid;
- if (notifier) {
- emit notifier->CBManagerError(serviceUuid,
- QLowEnergyService::UnknownError);
- }
+ if (notifier)
+ emit notifier->CBManagerError(serviceUuid, QLowEnergyService::UnknownError);
}
- (void)readCharacteristics:(CBService *)service
@@ -391,8 +477,10 @@ QT_END_NAMESPACE
NSArray *const cs = service.characteristics;
for (CBCharacteristic *c in cs) {
- if (c.properties & CBCharacteristicPropertyRead)
+ if (c.properties & CBCharacteristicPropertyRead) {
+ [self watchAfter:c timeout:OperationTimeout::characteristicRead];
return [peripheral readValueForCharacteristic:c];
+ }
}
// No readable properties? Discover descriptors then:
@@ -418,15 +506,18 @@ QT_END_NAMESPACE
[self serviceDetailsDiscoveryFinished:service];
} else {
// Start from 0 and continue in the callback.
- [peripheral discoverDescriptorsForCharacteristic:[service.characteristics objectAtIndex:0]];
+ CBCharacteristic *ch = [service.characteristics objectAtIndex:0];
+ [self watchAfter:ch timeout:OperationTimeout::descriptorsDiscovery];
+ [peripheral discoverDescriptorsForCharacteristic:ch];
}
}
- (void)readDescriptors:(CBService *)service
{
+ using namespace OSXBluetooth;
+
Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)");
- Q_ASSERT_X(managerState != OSXBluetooth::CentralManagerUpdating,
- Q_FUNC_INFO, "invalid state");
+ Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state");
Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
QT_BT_MAC_AUTORELEASEPOOL;
@@ -435,8 +526,11 @@ QT_END_NAMESPACE
// We can never be here if we have no characteristics.
Q_ASSERT_X(cs && cs.count, Q_FUNC_INFO, "invalid service");
for (CBCharacteristic *c in cs) {
- if (c.descriptors && c.descriptors.count)
- return [peripheral readValueForDescriptor:[c.descriptors objectAtIndex:0]];
+ if (c.descriptors && c.descriptors.count) {
+ CBDescriptor *desc = [c.descriptors objectAtIndex:0];
+ [self watchAfter:desc timeout:OperationTimeout::descriptorRead];
+ return [peripheral readValueForDescriptor:desc];
+ }
}
// No descriptors to read, done.
@@ -571,6 +665,8 @@ QT_END_NAMESPACE
requestPending = true;
currentReadHandle = request.handle;
+ // Timeouts: for now, we do not alert timeoutWatchdog - never had such
+ // bug reports and after all a read timeout can be handled externally.
[peripheral readValueForCharacteristic:charMap[request.handle]];
} else {
if (!descMap.contains(request.handle)) {
@@ -581,6 +677,7 @@ QT_END_NAMESPACE
requestPending = true;
currentReadHandle = request.handle;
+ // Timeouts: see the comment above (CharRead).
[peripheral readValueForDescriptor:descMap[request.handle]];
}
}
@@ -657,6 +754,7 @@ QT_END_NAMESPACE
return [self performNextRequest];
requestPending = true;
+ [self watchAfter:characteristic timeout:OperationTimeout::characteristicWrite];
[peripheral writeValue:data.data() forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
} else {
@@ -1021,6 +1119,7 @@ QT_END_NAMESPACE
charMap.clear();
descMap.clear();
currentReadHandle = 0;
+ [self stopWatchdog];
// TODO: also serviceToVisit/VisitNext and visitedServices ?
}
@@ -1030,6 +1129,9 @@ QT_END_NAMESPACE
{
using namespace OSXBluetooth;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
const auto state = central.state;
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (state == CBManagerStateUnknown
@@ -1072,12 +1174,14 @@ QT_END_NAMESPACE
#else
if (state == CBCentralManagerStatePoweredOff) {
#endif
- managerState = CentralManagerIdle;
+
if (managerState == CentralManagerUpdating) {
+ managerState = CentralManagerIdle;
// I've seen this instead of Unsupported on OS X.
if (notifier)
emit notifier->LEnotSupported();
} else {
+ managerState = CentralManagerIdle;
// TODO: we need a better error +
// what will happen if later the state changes to PoweredOn???
if (notifier)
@@ -1099,6 +1203,8 @@ QT_END_NAMESPACE
// We actually handled all known states, but .. Core Bluetooth can change?
Q_ASSERT_X(0, Q_FUNC_INFO, "invalid centra's state");
}
+
+#pragma clang diagnostic pop
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral
@@ -1162,10 +1268,16 @@ QT_END_NAMESPACE
Q_UNUSED(aPeripheral)
if (managerState != OSXBluetooth::CentralManagerDiscovering) {
- // Canceled by -disconnectFromDevice.
+ // Canceled by -disconnectFromDevice, or as a result of a timeout.
+ return;
+ }
+
+ if (objectUnderWatch != aPeripheral) {
+ // Timed out.
return;
}
+ [self stopWatchdog];
managerState = OSXBluetooth::CentralManagerIdle;
if (error) {
@@ -1173,9 +1285,9 @@ QT_END_NAMESPACE
// TODO: better error mapping required.
if (notifier)
emit notifier->CBManagerError(QLowEnergyController::UnknownError);
- } else {
- [self discoverIncludedServices];
}
+
+ [self discoverIncludedServices];
}
@@ -1191,10 +1303,16 @@ QT_END_NAMESPACE
return;
}
+ if (service != objectUnderWatch) {
+ // Timed out.
+ return;
+ }
+
QT_BT_MAC_AUTORELEASEPOOL;
Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
+ [self stopWatchdog];
managerState = CentralManagerIdle;
if (error) {
@@ -1217,6 +1335,7 @@ QT_END_NAMESPACE
// Continue with discovery ...
[visitedServices addObject:s];
managerState = CentralManagerDiscovering;
+ [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery];
return [peripheral discoverIncludedServices:nil forService:s];
}
}
@@ -1232,6 +1351,7 @@ QT_END_NAMESPACE
if (![visitedServices containsObject:s]) {
[visitedServices addObject:s];
managerState = CentralManagerDiscovering;
+ [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery];
return [peripheral discoverIncludedServices:nil forService:s];
}
}
@@ -1260,6 +1380,13 @@ QT_END_NAMESPACE
return;
}
+ if (service != objectUnderWatch) {
+ // Timed out already?
+ return;
+ }
+
+ [self stopWatchdog];
+
using namespace OSXBluetooth;
Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state");
@@ -1269,9 +1396,9 @@ QT_END_NAMESPACE
// We did not discover any characteristics and can not discover descriptors,
// inform our delegate (it will set a service state also).
emit notifier->CBManagerError(qt_uuid(service.UUID), QLowEnergyController::UnknownError);
- } else {
- [self readCharacteristics:service];
}
+
+ [self readCharacteristics:service];
}
- (void)peripheral:(CBPeripheral *)aPeripheral
@@ -1285,6 +1412,10 @@ QT_END_NAMESPACE
return;
}
+ const bool readMatch = characteristic == objectUnderWatch;
+ if (readMatch)
+ [self stopWatchdog];
+
using namespace OSXBluetooth;
Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state");
@@ -1311,13 +1442,17 @@ QT_END_NAMESPACE
}
if (isDetailsDiscovery) {
- // Test if we have any other characteristic to read yet.
- CBCharacteristic *const next = [self nextCharacteristicForService:characteristic.service
- startingFrom:characteristic properties:CBCharacteristicPropertyRead];
- if (next)
- [peripheral readValueForCharacteristic:next];
- else
- [self discoverDescriptors:characteristic.service];
+ if (readMatch) {
+ // Test if we have any other characteristic to read yet.
+ CBCharacteristic *const next = [self nextCharacteristicForService:characteristic.service
+ startingFrom:characteristic properties:CBCharacteristicPropertyRead];
+ if (next) {
+ [self watchAfter:next timeout:OperationTimeout::characteristicRead];
+ [peripheral readValueForCharacteristic:next];
+ } else {
+ [self discoverDescriptors:characteristic.service];
+ }
+ }
} else {
// This is (probably) the result of update notification.
// It's very possible we can have an invalid handle here (0) -
@@ -1360,6 +1495,11 @@ QT_END_NAMESPACE
QT_BT_MAC_AUTORELEASEPOOL;
+ if (characteristic != objectUnderWatch)
+ return;
+
+ [self stopWatchdog];
+
using namespace OSXBluetooth;
if (error) {
@@ -1370,10 +1510,12 @@ QT_END_NAMESPACE
// Do we have more characteristics on this service to discover descriptors?
CBCharacteristic *const next = [self nextCharacteristicForService:characteristic.service
startingFrom:characteristic];
- if (next)
+ if (next) {
+ [self watchAfter:next timeout:OperationTimeout::descriptorsDiscovery];
[peripheral discoverDescriptorsForCharacteristic:next];
- else
+ } else {
[self readDescriptors:characteristic.service];
+ }
}
- (void)peripheral:(CBPeripheral *)aPeripheral
@@ -1391,6 +1533,11 @@ QT_END_NAMESPACE
QT_BT_MAC_AUTORELEASEPOOL;
+ if (descriptor != objectUnderWatch)
+ return;
+
+ [self stopWatchdog];
+
using namespace OSXBluetooth;
CBService *const service = descriptor.characteristic.service;
@@ -1417,6 +1564,7 @@ QT_END_NAMESPACE
CBDescriptor *const next = [self nextDescriptorForCharacteristic:descriptor.characteristic
startingFrom:descriptor];
if (next) {
+ [self watchAfter:next timeout:OperationTimeout::descriptorRead];
[peripheral readValueForDescriptor:next];
} else {
// We either have to read a value for a next descriptor
@@ -1426,8 +1574,11 @@ QT_END_NAMESPACE
CBCharacteristic *nextCh = [self nextCharacteristicForService:ch.service
startingFrom:ch];
while (nextCh) {
- if (nextCh.descriptors && nextCh.descriptors.count)
- return [peripheral readValueForDescriptor:[nextCh.descriptors objectAtIndex:0]];
+ if (nextCh.descriptors && nextCh.descriptors.count) {
+ CBDescriptor *desc = [nextCh.descriptors objectAtIndex:0];
+ [self watchAfter:desc timeout:OperationTimeout::descriptorRead];
+ return [peripheral readValueForDescriptor:desc];
+ }
nextCh = [self nextCharacteristicForService:ch.service
startingFrom:nextCh];
@@ -1474,6 +1625,10 @@ QT_END_NAMESPACE
QT_BT_MAC_AUTORELEASEPOOL;
+ if (characteristic != objectUnderWatch)
+ return;
+
+ [self stopWatchdog];
requestPending = false;
@@ -1569,9 +1724,10 @@ QT_END_NAMESPACE
if (notifier) {
notifier->disconnect();
notifier->deleteLater();
- notifier = 0;
+ notifier = nullptr;
}
+ [self stopWatchdog];
[self disconnectFromDevice];
}
diff --git a/src/bluetooth/osx/osxbtcentralmanager_p.h b/src/bluetooth/osx/osxbtcentralmanager_p.h
index 697d922c..e172d874 100644
--- a/src/bluetooth/osx/osxbtcentralmanager_p.h
+++ b/src/bluetooth/osx/osxbtcentralmanager_p.h
@@ -53,6 +53,7 @@
#include "qlowenergycontroller.h"
#include "qlowenergyservice.h"
+#include "osxbtgcdtimer_p.h"
#include "qbluetoothuuid.h"
#include "osxbtutility_p.h"
#include "osxbluetooth_p.h"
@@ -86,6 +87,18 @@ enum CentralManagerState
CentralManagerDisconnecting
};
+enum class OperationTimeout
+{
+ none,
+ serviceDiscovery,
+ includedServicesDiscovery,
+ characteristicsDiscovery,
+ characteristicRead,
+ descriptorsDiscovery,
+ descriptorRead,
+ characteristicWrite
+};
+
// In Qt we work with handles and UUIDs. Core Bluetooth
// has NSArrays (and nested NSArrays inside servces/characteristics).
// To simplify a navigation, I need a simple way to map from a handle
@@ -132,7 +145,9 @@ typedef QHash<NSObject *, QByteArray> ValueHash;
QT_END_NAMESPACE
-@interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) : NSObject<CBCentralManagerDelegate, CBPeripheralDelegate>
+@interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) : NSObject<CBCentralManagerDelegate,
+ CBPeripheralDelegate,
+ QT_MANGLE_NAMESPACE(GCDTimerDelegate)>
{
@private
CBCentralManager *manager;
@@ -166,6 +181,12 @@ QT_END_NAMESPACE
QT_PREPEND_NAMESPACE(QLowEnergyHandle) currentReadHandle;
QT_PREPEND_NAMESPACE(OSXBluetooth)::ValueHash valuesToWrite;
+
+ qint64 timeoutMS;
+ id objectUnderWatch;
+ QT_PREPEND_NAMESPACE(OSXBluetooth)::OperationTimeout timeoutType;
+ QT_PREPEND_NAMESPACE(OSXBluetooth)::GCDTimer timeoutWatchdog;
+
@public
CBPeripheral *peripheral;
}
diff --git a/src/bluetooth/osx/osxbtgcdtimer.mm b/src/bluetooth/osx/osxbtgcdtimer.mm
new file mode 100644
index 00000000..095f8680
--- /dev/null
+++ b/src/bluetooth/osx/osxbtgcdtimer.mm
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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 "osxbtgcdtimer_p.h"
+#include "osxbtutility_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <algorithm>
+
+@implementation QT_MANGLE_NAMESPACE(OSXBTGCDTimer)
+
+- (instancetype)initWithDelegate:(id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)>)delegate
+{
+ if (self = [super init]) {
+ timeoutHandler = delegate;
+ timeoutMS = 0;
+ timeoutStepMS = 0;
+ cancelled = false;
+ }
+ return self;
+}
+
+- (void)startWithTimeout:(qint64)ms step:(qint64)stepMS
+{
+ Q_ASSERT(!timeoutMS && !timeoutStepMS);
+ Q_ASSERT(!cancelled);
+
+ if (!timeoutHandler) {
+ // Nobody to report timeout to, no need to start any task then.
+ return;
+ }
+
+ if (ms <= 0 || stepMS <= 0) {
+ qCWarning(QT_BT_OSX, "Invalid timeout/step parameters");
+ return;
+ }
+
+ timeoutMS = ms;
+ timeoutStepMS = stepMS;
+ timer.start();
+
+ [self handleTimeout];
+}
+
+- (void)handleTimeout
+{
+ if (cancelled)
+ return;
+
+ const qint64 elapsed = timer.elapsed();
+ if (elapsed >= timeoutMS) {
+ [timeoutHandler timeout];
+ } else {
+ using namespace QT_PREPEND_NAMESPACE(OSXBluetooth);
+ // Re-schedule:
+ dispatch_queue_t leQueue(qt_LE_queue());
+ Q_ASSERT(leQueue);
+ const qint64 timeChunkMS = std::min(timeoutMS - elapsed, timeoutStepMS);
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
+ int64_t(timeChunkMS / 1000. * NSEC_PER_SEC)),
+ leQueue,
+ ^{
+ [self handleTimeout];
+ });
+ }
+}
+
+- (void)cancelTimer
+{
+ cancelled = true;
+ timeoutHandler = nil;
+}
+
+@end
diff --git a/src/bluetooth/osx/osxbtgcdtimer_p.h b/src/bluetooth/osx/osxbtgcdtimer_p.h
new file mode 100644
index 00000000..007a004b
--- /dev/null
+++ b/src/bluetooth/osx/osxbtgcdtimer_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef OSXBTGCDTIMER_P_H
+#define OSXBTGCDTIMER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "osxbtutility_p.h"
+
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qglobal.h>
+
+#include <Foundation/Foundation.h>
+
+@protocol QT_MANGLE_NAMESPACE(GCDTimerDelegate)
+@required
+- (void)timeout;
+@end
+
+@interface QT_MANGLE_NAMESPACE(OSXBTGCDTimer) : NSObject {
+@private
+ qint64 timeoutMS;
+ qint64 timeoutStepMS;
+ QT_PREPEND_NAMESPACE(QElapsedTimer) timer;
+ id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)> timeoutHandler;
+ bool cancelled;
+}
+
+- (instancetype)initWithDelegate:(id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)>)delegate;
+- (void)startWithTimeout:(qint64)ms step:(qint64)stepMS;
+- (void)handleTimeout;
+- (void)cancelTimer;
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+namespace OSXBluetooth {
+
+using GCDTimerObjC = QT_MANGLE_NAMESPACE(OSXBTGCDTimer);
+using GCDTimer = ObjCScopedPointer<GCDTimerObjC>;
+
+}
+
+QT_END_NAMESPACE
+
+#endif // OSXBTGCDTIMER_P_H
+
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm
index 7a516dd4..2cece15b 100644
--- a/src/bluetooth/osx/osxbtledeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm
@@ -65,9 +65,7 @@ QBluetoothUuid qt_uuid(NSUUID *nsUuid)
}
const int timeStepMS = 100;
-
const int powerOffTimeoutMS = 30000;
-const qreal powerOffTimeStepS = 30. / 100.;
struct AdvertisementData {
// That's what CoreBluetooth has:
@@ -115,14 +113,6 @@ QT_END_NAMESPACE
QT_USE_NAMESPACE
-@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) (PrivateAPI) <CBCentralManagerDelegate>
-// These two methods are scheduled with a small time step
-// within a given timeout, they either re-schedule
-// themselves or emit a signal/stop some operation.
-- (void)stopScan;
-- (void)handlePoweredOff;
-@end
-
@implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry)
-(id)initWithNotifier:(LECBManagerNotifier *)aNotifier
@@ -153,60 +143,22 @@ QT_USE_NAMESPACE
[super dealloc];
}
-- (void)stopScan
+- (void)timeout
{
- using namespace OSXBluetooth;
-
- // We never schedule stopScan if there is no timeout:
- Q_ASSERT(inquiryTimeoutMS > 0);
-
if (internalState == InquiryActive) {
- const int elapsed = scanTimer.elapsed();
- if (elapsed >= inquiryTimeoutMS) {
- [manager stopScan];
- [manager setDelegate:nil];
- internalState = InquiryFinished;
- Q_ASSERT(notifier);
- emit notifier->discoveryFinished();
- } else {
- // Re-schedule 'stopScan':
- dispatch_queue_t leQueue(qt_LE_queue());
- Q_ASSERT(leQueue);
- const int timeChunkMS = std::min(inquiryTimeoutMS - elapsed, timeStepMS);
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
- int64_t(timeChunkMS / 1000. * NSEC_PER_SEC)),
- leQueue,
- ^{
- [self stopScan];
- });
- }
- }
-}
-
-- (void)handlePoweredOff
-{
- // This is interesting on iOS only, where
- // the system shows an alert asking to enable
- // Bluetooth in the 'Settings' app. If not done yet (after 30
- // seconds) - we consider it an error.
- using namespace OSXBluetooth;
-
- if (internalState == InquiryStarting) {
- if (errorTimer.elapsed() >= powerOffTimeoutMS) {
- [manager setDelegate:nil];
- internalState = ErrorPoweredOff;
- Q_ASSERT(notifier);
- emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
- } else {
- dispatch_queue_t leQueue(qt_LE_queue());
- Q_ASSERT(leQueue);
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
- (int64_t)(powerOffTimeStepS * NSEC_PER_SEC)),
- leQueue,
- ^{
- [self handlePoweredOff];
- });
- }
+ [manager stopScan];
+ [manager setDelegate:nil];
+ internalState = InquiryFinished;
+ Q_ASSERT(notifier);
+ emit notifier->discoveryFinished();
+ } else if (internalState == InquiryStarting) {
+ // This is interesting on iOS only, where the system shows an alert
+ // asking to enable Bluetooth in the 'Settings' app. If not done yet
+ // (after 30 seconds) - we consider this as an error.
+ [manager setDelegate:nil];
+ internalState = ErrorPoweredOff;
+ Q_ASSERT(notifier);
+ emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
}
}
@@ -220,6 +172,9 @@ QT_USE_NAMESPACE
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
if (central != manager)
return;
@@ -230,9 +185,6 @@ QT_USE_NAMESPACE
using namespace OSXBluetooth;
- dispatch_queue_t leQueue(qt_LE_queue());
- Q_ASSERT(leQueue);
-
const auto state = central.state;
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (state == CBManagerStatePoweredOn) {
@@ -243,18 +195,9 @@ QT_USE_NAMESPACE
internalState = InquiryActive;
if (inquiryTimeoutMS > 0) {
- // We have a finite-length discovery, schedule stopScan,
- // with a smaller time step, otherwise it can prevent
- // 'self' from being deleted in time, which is not good
- // (the block will retain 'self', waiting for timeout).
- scanTimer.start();
- const int timeChunkMS = std::min(timeStepMS, inquiryTimeoutMS);
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
- int64_t(timeChunkMS / 1000. * NSEC_PER_SEC)),
- leQueue,
- ^{
- [self stopScan];
- });
+ [elapsedTimer cancelTimer];
+ elapsedTimer.reset([[GCDTimerObjC alloc] initWithDelegate:self]);
+ [elapsedTimer startWithTimeout:inquiryTimeoutMS step:timeStepMS];
}
[manager scanForPeripheralsWithServices:nil options:nil];
@@ -284,19 +227,15 @@ QT_USE_NAMESPACE
if (internalState == InquiryStarting) {
#ifndef Q_OS_OSX
// On iOS a user can see at this point an alert asking to
- // enable Bluetooth in the "Settings" app. If a user does,
+ // enable Bluetooth in the "Settings" app. If a user does so,
// we'll receive 'PoweredOn' state update later.
- // No change in internalState. Wait for 30 seconds
- // (we split it into smaller steps not to retain 'self' for
- // too long ) ...
- errorTimer.start();
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
- (int64_t)(powerOffTimeStepS * NSEC_PER_SEC)),
- leQueue,
- ^{
- [self handlePoweredOff];
- });
+ // No change in internalState. Wait for 30 seconds.
+ [elapsedTimer cancelTimer];
+ elapsedTimer.reset([[GCDTimerObjC alloc] initWithDelegate:self]);
+ [elapsedTimer startWithTimeout:powerOffTimeoutMS step:300];
return;
+#else
+ Q_UNUSED(powerOffTimeoutMS)
#endif
internalState = ErrorPoweredOff;
emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError);
@@ -318,6 +257,8 @@ QT_USE_NAMESPACE
// lost; an update is imminent. "
// Wait for this imminent update.
}
+
+#pragma clang diagnostic pop
}
- (void)stop
@@ -325,6 +266,8 @@ QT_USE_NAMESPACE
if (internalState == InquiryActive)
[manager stopScan];
+ [elapsedTimer cancelTimer];
+
[manager setDelegate:nil];
internalState = InquiryCancelled;
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry_p.h b/src/bluetooth/osx/osxbtledeviceinquiry_p.h
index fc787a6d..a19055ab 100644
--- a/src/bluetooth/osx/osxbtledeviceinquiry_p.h
+++ b/src/bluetooth/osx/osxbtledeviceinquiry_p.h
@@ -53,10 +53,10 @@
#include "qbluetoothdevicediscoveryagent.h"
#include "qbluetoothdeviceinfo.h"
+#include "osxbtgcdtimer_p.h"
#include "osxbtutility_p.h"
#include "osxbluetooth_p.h"
-#include <QtCore/qelapsedtimer.h>
#include <QtCore/qglobal.h>
#include <QtCore/qlist.h>
@@ -75,10 +75,8 @@ class LECBManagerNotifier;
QT_END_NAMESPACE
-// Ugly but all these QT_PREPEND_NAMESPACE etc. are even worse ...
-using OSXBluetooth::LECBManagerNotifier;
-using OSXBluetooth::ObjCScopedPointer;
-using QT_PREPEND_NAMESPACE(QElapsedTimer);
+using QT_PREPEND_NAMESPACE(OSXBluetooth)::LECBManagerNotifier;
+using QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCScopedPointer;
enum LEInquiryState
{
@@ -90,7 +88,7 @@ enum LEInquiryState
ErrorLENotSupported
};
-@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) : NSObject
+@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) : NSObject<CBCentralManagerDelegate, QT_MANGLE_NAMESPACE(GCDTimerDelegate)>
{
LECBManagerNotifier *notifier;
ObjCScopedPointer<CBCentralManager> manager;
@@ -99,16 +97,14 @@ enum LEInquiryState
LEInquiryState internalState;
int inquiryTimeoutMS;
- // Timers to check if we can execute delayed callbacks:
- QT_PREPEND_NAMESPACE(QElapsedTimer) errorTimer;
- QT_PREPEND_NAMESPACE(QElapsedTimer) scanTimer;
+ QT_PREPEND_NAMESPACE(OSXBluetooth)::GCDTimer elapsedTimer;
}
- (id)initWithNotifier:(LECBManagerNotifier *)aNotifier;
- (void)dealloc;
-// IMPORTANT: both 'startWithTimeout' and 'stop'
-// can be executed only on the "Qt's LE queue".
+// IMPORTANT: both 'startWithTimeout' and 'stop' MUST be executed on the "Qt's
+// LE queue".
- (void)startWithTimeout:(int)timeout;
- (void)stop;
diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm
index 64c8cd90..d3d92f41 100644
--- a/src/bluetooth/osx/osxbtperipheralmanager.mm
+++ b/src/bluetooth/osx/osxbtperipheralmanager.mm
@@ -388,6 +388,9 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
if (peripheral != manager || !notifier)
return;
@@ -436,6 +439,8 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
emit notifier->LEnotSupported();
state = PeripheralState::idle;
}
+
+#pragma clang diagnostic pop
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 303dd67f..c7afd578 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -147,23 +147,33 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
}
// check Android v23+ permissions
- // -> BTLE search requires android.permission.ACCESS_COARSE_LOCATION
+ // -> BTLE search requires android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION
if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod
&& QtAndroid::androidSdkVersion() >= 23)
{
- QString permission(QLatin1String("android.permission.ACCESS_COARSE_LOCATION"));
+ const QString coarsePermission(QLatin1String("android.permission.ACCESS_COARSE_LOCATION"));
+ const QString finePermission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
// do we have required permission already, if so nothing to do
- if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) {
- qCWarning(QT_BT_ANDROID) << "Requesting ACCESS_COARSE_LOCATION permission";
+ if (QtAndroidPrivate::checkPermission(coarsePermission) == QtAndroidPrivate::PermissionsResult::Denied
+ && QtAndroidPrivate::checkPermission(finePermission) == QtAndroidPrivate::PermissionsResult::Denied) {
+ qCWarning(QT_BT_ANDROID) << "Requesting ACCESS_*_LOCATION permission";
QAndroidJniEnvironment env;
const QHash<QString, QtAndroidPrivate::PermissionsResult> results =
- QtAndroidPrivate::requestPermissionsSync(env, QStringList() << permission);
- if (!results.contains(permission)
- || results[permission] == QtAndroidPrivate::PermissionsResult::Denied)
- {
- qCWarning(QT_BT_ANDROID) << "Search not possible due to missing permission (ACCESS_COARSE_LOCATION)";
+ QtAndroidPrivate::requestPermissionsSync(env, QStringList() << coarsePermission << finePermission);
+
+ bool permissionReceived = false;
+ for (const QString &permission: results.keys()) {
+ qCDebug(QT_BT_ANDROID) << permission << (results[permission] == QtAndroidPrivate::PermissionsResult::Denied);
+ if ((permission == coarsePermission || permission == finePermission)
+ && results[permission] == QtAndroidPrivate::PermissionsResult::Granted) {
+ permissionReceived = true;
+ break;
+ }
+ }
+ if (!permissionReceived) {
+ qCWarning(QT_BT_ANDROID) << "Search not possible due to missing permission (ACCESS_COARSE|FINE_LOCATION)";
lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
errorString = QBluetoothDeviceDiscoveryAgent::tr("Missing Location permission. Search is not possible.");
emit q->error(lastError);
@@ -171,7 +181,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
}
}
- qCWarning(QT_BT_ANDROID) << "ACCESS_COARSE_LOCATION permission available";
+ qCWarning(QT_BT_ANDROID) << "ACCESS_COARSE|FINE_LOCATION permission available";
}
// install Java BroadcastReceiver
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index 243d7fd2..15758195 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -78,6 +78,11 @@ class QDBusVariant;
QT_END_NAMESPACE
#endif
+#ifdef QT_WINRT_BLUETOOTH
+#include <QtCore/QPointer>
+#include <QtCore/QTimer>
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef QT_WINRT_BLUETOOTH
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index 6786ac54..309804a8 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -92,7 +92,7 @@ private:
QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
void gatherDeviceInformation(IDeviceInformation *deviceInfo,
QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
- void gatherMultipleDeviceInformation(IVectorView<DeviceInformation *> *devices,
+ void gatherMultipleDeviceInformation(quint32 deviceCount, IVectorView<DeviceInformation *> *devices,
QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
void setupLEDeviceWatcher();
void classicBluetoothInfoFromDeviceIdAsync(HSTRING deviceId);
@@ -207,7 +207,20 @@ void QWinRTBluetoothDeviceDiscoveryWorker::onDeviceDiscoveryFinished(IAsyncOpera
HRESULT hr;
hr = op->GetResults(&devices);
Q_ASSERT_SUCCEEDED(hr);
- gatherMultipleDeviceInformation(devices.Get(), mode);
+ quint32 deviceCount;
+ hr = devices->get_Size(&deviceCount);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // For classic discovery only paired devices will be found. If we only do classic disovery and
+ // no device is found, the scan is finished.
+ if (requestedModes == QBluetoothDeviceDiscoveryAgent::ClassicMethod &&
+ deviceCount == 0) {
+ finishDiscovery();
+ return;
+ }
+
+ m_pendingPairedDevices += deviceCount;
+ gatherMultipleDeviceInformation(deviceCount, devices.Get(), mode);
}
void QWinRTBluetoothDeviceDiscoveryWorker::gatherDeviceInformation(IDeviceInformation *deviceInfo, QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode)
@@ -222,15 +235,11 @@ void QWinRTBluetoothDeviceDiscoveryWorker::gatherDeviceInformation(IDeviceInform
classicBluetoothInfoFromDeviceIdAsync(deviceId.Get());
}
-void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(IVectorView<DeviceInformation *> *devices, QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode)
+void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(quint32 deviceCount, IVectorView<DeviceInformation *> *devices, QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode)
{
- quint32 deviceCount;
- HRESULT hr = devices->get_Size(&deviceCount);
- Q_ASSERT_SUCCEEDED(hr);
- m_pendingPairedDevices += deviceCount;
for (quint32 i = 0; i < deviceCount; ++i) {
ComPtr<IDeviceInformation> device;
- hr = devices->GetAt(i, &device);
+ HRESULT hr = devices->GetAt(i, &device);
Q_ASSERT_SUCCEEDED(hr);
gatherDeviceInformation(device.Get(), mode);
}
@@ -374,34 +383,39 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun
Q_ASSERT_SUCCEEDED(hr);
IVectorView <Rfcomm::RfcommDeviceService *> *deviceServices;
hr = device->get_RfcommServices(&deviceServices);
- Q_ASSERT_SUCCEEDED(hr);
- uint serviceCount;
- hr = deviceServices->get_Size(&serviceCount);
- Q_ASSERT_SUCCEEDED(hr);
- QList<QBluetoothUuid> uuids;
- for (uint i = 0; i < serviceCount; ++i) {
- ComPtr<Rfcomm::IRfcommDeviceService> service;
- hr = deviceServices->GetAt(i, &service);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Rfcomm::IRfcommServiceId> id;
- hr = service->get_ServiceId(&id);
+ if (hr == E_ACCESSDENIED) {
+ qCWarning(QT_BT_WINRT) << "Could not obtain device services. Please check you have "
+ "permission to access the device.";
+ } else {
Q_ASSERT_SUCCEEDED(hr);
- GUID uuid;
- hr = id->get_Uuid(&uuid);
+ uint serviceCount;
+ hr = deviceServices->get_Size(&serviceCount);
Q_ASSERT_SUCCEEDED(hr);
- uuids.append(QBluetoothUuid(uuid));
- }
+ QList<QBluetoothUuid> uuids;
+ for (uint i = 0; i < serviceCount; ++i) {
+ ComPtr<Rfcomm::IRfcommDeviceService> service;
+ hr = deviceServices->GetAt(i, &service);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<Rfcomm::IRfcommServiceId> id;
+ hr = service->get_ServiceId(&id);
+ Q_ASSERT_SUCCEEDED(hr);
+ GUID uuid;
+ hr = id->get_Uuid(&uuid);
+ Q_ASSERT_SUCCEEDED(hr);
+ uuids.append(QBluetoothUuid(uuid));
+ }
- qCDebug(QT_BT_WINRT) << "Discovered BT device: " << QString::number(address) << btName
- << "Num UUIDs" << uuids.count();
+ qCDebug(QT_BT_WINRT) << "Discovered BT device: " << QString::number(address) << btName
+ << "Num UUIDs" << uuids.count();
- QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, classOfDeviceInt);
- info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
- info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
- info.setCached(true);
+ QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, classOfDeviceInt);
+ info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
+ info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setCached(true);
- QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
- Q_ARG(QBluetoothDeviceInfo, info));
+ QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
+ Q_ARG(QBluetoothDeviceInfo, info));
+ }
if (!m_pendingPairedDevices && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod))
finishDiscovery();
return S_OK;
diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp
index e2378460..78095beb 100644
--- a/src/bluetooth/qbluetoothlocaldevice.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice.cpp
@@ -55,6 +55,9 @@ QT_BEGIN_NAMESPACE
QBluetoothLocalDevice provides functions for getting and setting the state of local Bluetooth
devices.
+
+ On iOS and Windows, this class cannot be used because the platform does not expose
+ any data or API which may provide information on the local Bluetooth device.
*/
/*!
@@ -267,9 +270,9 @@ bool QBluetoothLocalDevice::isValid() const
*/
/*!
- \fn QBluetoothLocalDevice::pairingConfirmation(bool accept)
+ \fn QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
- To be called after getting a pairingDisplayConfirmation(). The \a accept parameter either
+ To be called after getting a pairingDisplayConfirmation(). The \a confirmation parameter either
accepts the pairing or rejects it.
Accepting a pairing always refers to the last pairing request issued via \l requestPairing().
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index 0982573e..c247f679 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -529,16 +529,20 @@ void QBluetoothLocalDevicePrivate::processPairingBluez5(const QString &objectPat
switch (target) {
case QBluetoothLocalDevice::Unpaired: {
delete pairingTarget;
- pairingTarget = 0;
+ pairingTarget = nullptr;
QDBusPendingReply<> removeReply = adapterBluez5->RemoveDevice(QDBusObjectPath(objectPath));
- removeReply.waitForFinished();
-
- if (removeReply.isError())
- emit q->error(QBluetoothLocalDevice::PairingError);
- else
- emit q->pairingFinished(targetAddress, QBluetoothLocalDevice::Unpaired);
+ auto watcher = new QDBusPendingCallWatcher(removeReply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, [q, targetAddress](QDBusPendingCallWatcher* watcher){
+ QDBusPendingReply<> reply = *watcher;
+ if (reply.isError())
+ emit q->error(QBluetoothLocalDevice::PairingError);
+ else
+ emit q->pairingFinished(targetAddress, QBluetoothLocalDevice::Unpaired);
+ watcher->deleteLater();
+ });
break;
}
case QBluetoothLocalDevice::Paired:
@@ -800,7 +804,7 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
SLOT(PropertyChanged(QString, QDBusVariant)));
agent_path = agentPath;
- agent_path.append(QString::fromLatin1("/%1").arg(QRandomGenerator::get32()));
+ agent_path.append(QString::fromLatin1("/%1").arg(QRandomGenerator::global()->generate()));
}
}
@@ -1164,7 +1168,7 @@ QString QBluetoothLocalDevicePrivate::RequestPinCode(const QDBusObjectPath &in0)
Q_Q(QBluetoothLocalDevice);
qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << in0.path();
// seeded in constructor, 6 digit pin
- QString pin = QString::fromLatin1("%1").arg(QRandomGenerator::bounded(1000000));
+ QString pin = QString::fromLatin1("%1").arg(QRandomGenerator::global()->bounded(1000000));
pin = QString::fromLatin1("%1").arg(pin, 6, QLatin1Char('0'));
emit q->pairingDisplayPinCode(address, pin);
@@ -1276,7 +1280,7 @@ uint QBluetoothLocalDevicePrivate::RequestPasskey(const QDBusObjectPath &in0)
{
Q_UNUSED(in0);
qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
- return (QRandomGenerator::bounded(1000000));
+ return (QRandomGenerator::global()->bounded(1000000));
}
// Bluez 4
diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp
index 99d3b53a..d9e42adf 100644
--- a/src/bluetooth/qbluetoothserver.cpp
+++ b/src/bluetooth/qbluetoothserver.cpp
@@ -66,6 +66,9 @@ QT_BEGIN_NAMESPACE
If the \l QBluetoothServiceInfo::Protocol is not supported by a platform, \l listen() will return \c false.
Android and WinRT only support RFCOMM for example.
+ On iOS, this class cannot be used because the platform does not expose
+ an API which may permit access to QBluetoothServer related features.
+
\sa QBluetoothServiceInfo, QBluetoothSocket
*/
@@ -186,7 +189,7 @@ QBluetoothServer::~QBluetoothServer()
required to call \l QBluetoothServiceInfo::unregisterService() and \l close() on this
server object.
- Returns a registered QBluetoothServiceInfo instance if sucessful otherwise an
+ Returns a registered QBluetoothServiceInfo instance if successful otherwise an
invalid QBluetoothServiceInfo. This function always assumes that the default Bluetooth adapter
should be used.
diff --git a/src/bluetooth/qbluetoothserver_android.cpp b/src/bluetooth/qbluetoothserver_android.cpp
index 7d3d3588..b001adb8 100644
--- a/src/bluetooth/qbluetoothserver_android.cpp
+++ b/src/bluetooth/qbluetoothserver_android.cpp
@@ -41,7 +41,7 @@
#include "qbluetoothserver.h"
#include "qbluetoothserver_p.h"
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_android_p.h"
#include "qbluetoothlocaldevice.h"
#include "android/serveracceptancethread_p.h"
diff --git a/src/bluetooth/qbluetoothserver_osx.mm b/src/bluetooth/qbluetoothserver_osx.mm
index a1774d14..d7f29ed3 100644
--- a/src/bluetooth/qbluetoothserver_osx.mm
+++ b/src/bluetooth/qbluetoothserver_osx.mm
@@ -43,7 +43,7 @@
// The order is important: a workround for
// a private header included by private header
// (incorrectly handled dependencies).
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocketbase_p.h"
#include "qbluetoothsocket_osx_p.h"
#include "qbluetoothlocaldevice.h"
diff --git a/src/bluetooth/qbluetoothserver_p.h b/src/bluetooth/qbluetoothserver_p.h
index 4abadc72..9c414cdb 100644
--- a/src/bluetooth/qbluetoothserver_p.h
+++ b/src/bluetooth/qbluetoothserver_p.h
@@ -70,6 +70,8 @@ class ServerAcceptanceThread;
#endif
#ifdef QT_WINRT_BLUETOOTH
+#include <QtCore/QMutex>
+
#include <wrl.h>
// No forward declares because QBluetoothServerPrivate::listener does not work with them
#include <windows.networking.sockets.h>
diff --git a/src/bluetooth/qbluetoothserver_winrt.cpp b/src/bluetooth/qbluetoothserver_winrt.cpp
index 08aa45b4..a53ef110 100644
--- a/src/bluetooth/qbluetoothserver_winrt.cpp
+++ b/src/bluetooth/qbluetoothserver_winrt.cpp
@@ -40,7 +40,7 @@
#include "qbluetoothserver.h"
#include "qbluetoothserver_p.h"
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_winrt_p.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
index d6163f0e..05d62ab1 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
@@ -85,6 +85,9 @@ QT_BEGIN_NAMESPACE
Energy services, it is likely to not advertise them via SDP. The \l QLowEnergyController class
should be utilized to perform the service discovery on Low Energy devices.
+ On iOS, this class cannot be used because the platform does not expose
+ an API which may permit access to QBluetoothServiceDiscoveryAgent related features.
+
\sa QBluetoothDeviceDiscoveryAgent, QLowEnergyController
*/
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
index c4ea20a9..2a57c531 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
@@ -72,6 +72,10 @@ class QXmlStreamReader;
QT_END_NAMESPACE
#endif
+#ifdef QT_WINRT_BLUETOOTH
+#include <QtCore/QPointer>
+#endif
+
QT_BEGIN_NAMESPACE
class QBluetoothDeviceDiscoveryAgent;
diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp
index e4e5d1ed..d706e4a7 100644
--- a/src/bluetooth/qbluetoothserviceinfo.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo.cpp
@@ -105,6 +105,8 @@ QT_BEGIN_NAMESPACE
service info object share the same data as they do not detach upon changing them. This
ensures that two copies can (de)register the same Bluetooth service.
+ On iOS, this class cannot be used because the platform does not expose
+ an API which may permit access to QBluetoothServiceInfo related features.
*/
/*!
@@ -625,7 +627,7 @@ QDebug operator<<(QDebug dbg, const QBluetoothServiceInfo &info)
QDebugStateSaver saver(dbg);
dbg.noquote() << "\n";
foreach (quint16 id, info.attributes()) {
- dumpAttributeVariant(dbg, info.attribute(id), QString::fromLatin1("(%1)\t").arg(id));
+ dumpAttributeVariant(dbg, info.attribute(id), QStringLiteral("(%1)\t").arg(id));
}
return dbg;
}
diff --git a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
index 975a3f4a..fd77662a 100644
--- a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
@@ -340,7 +340,12 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca
hr = providerStatics->CreateAsync(serviceId.Get(), &op);
Q_ASSERT_SUCCEEDED(hr);
hr = QWinRTFunctions::await(op, serviceProvider.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
+ if (hr == HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE)) {
+ qCWarning(QT_BT_WINRT) << Q_FUNC_INFO << "No bluetooth adapter available.";
+ return false;
+ } else {
+ Q_ASSERT_SUCCEEDED(hr);
+ }
ComPtr<IStreamSocketListener> listener = sPriv->listener();
if (!listener) {
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index a35863b4..dae844d7 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -39,13 +39,18 @@
****************************************************************************/
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#if QT_CONFIG(bluez)
+#include "qbluetoothsocket_bluez_p.h"
+#elif defined(QT_ANDROID_BLUETOOTH)
+#include "qbluetoothsocket_android_p.h"
+#elif defined(QT_WINRT_BLUETOOTH)
+#include "qbluetoothsocket_winrt_p.h"
+#else
+#include "qbluetoothsocket_dummy_p.h"
+#endif
-#include "qbluetoothdeviceinfo.h"
-#include "qbluetoothserviceinfo.h"
#include "qbluetoothservicediscoveryagent.h"
-
#include <QtCore/QLoggingCategory>
#include <QSocketNotifier>
@@ -81,6 +86,9 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
\note QBluetoothSocket does not support synchronous read and write operations. Functions such
as \l waitForReadyRead() and \l waitForBytesWritten() are not implemented. I/O operations should be
performed using \l readyRead(), \l read() and \l write().
+
+ On iOS, this class cannot be used because the platform does not expose
+ an API which may permit access to QBluetoothSocket related features.
*/
/*!
@@ -247,11 +255,20 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
Constructs a Bluetooth socket of \a socketType type, with \a parent.
*/
QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent)
-: QIODevice(parent), d_ptr(new QBluetoothSocketPrivate)
-{
+: QIODevice(parent)
+{
+#if QT_CONFIG(bluez)
+ d_ptr = new QBluetoothSocketPrivateBluez();
+#elif defined(QT_ANDROID_BLUETOOTH)
+ d_ptr = new QBluetoothSocketPrivateAndroid();
+#elif defined(QT_WINRT_BLUETOOTH)
+ d_ptr = new QBluetoothSocketPrivateWinRT();
+#else
+ d_ptr = new QBluetoothSocketPrivateDummy();
+#endif
d_ptr->q_ptr = this;
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
d->ensureNativeSocket(socketType);
setOpenMode(QIODevice::NotOpen);
@@ -261,8 +278,17 @@ QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, Q
Constructs a Bluetooth socket with \a parent.
*/
QBluetoothSocket::QBluetoothSocket(QObject *parent)
- : QIODevice(parent), d_ptr(new QBluetoothSocketPrivate)
-{
+ : QIODevice(parent)
+{
+#if QT_CONFIG(bluez)
+ d_ptr = new QBluetoothSocketPrivateBluez();
+#elif defined(QT_ANDROID_BLUETOOTH)
+ d_ptr = new QBluetoothSocketPrivateAndroid();
+#elif defined(QT_WINRT_BLUETOOTH)
+ d_ptr = new QBluetoothSocketPrivateWinRT();
+#else
+ d_ptr = new QBluetoothSocketPrivateDummy();
+#endif
d_ptr->q_ptr = this;
setOpenMode(QIODevice::NotOpen);
}
@@ -291,7 +317,7 @@ bool QBluetoothSocket::isSequential() const
*/
qint64 QBluetoothSocket::bytesAvailable() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return QIODevice::bytesAvailable() + d->bytesAvailable();
}
@@ -301,7 +327,7 @@ qint64 QBluetoothSocket::bytesAvailable() const
*/
qint64 QBluetoothSocket::bytesToWrite() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->bytesToWrite();
}
@@ -324,64 +350,17 @@ qint64 QBluetoothSocket::bytesToWrite() const
*/
void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
+ d->connectToService(service, openMode);
+}
- if (state() != QBluetoothSocket::UnconnectedState && state() != QBluetoothSocket::ServiceLookupState) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
- d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
- setSocketError(QBluetoothSocket::OperationError);
- return;
- }
-#if defined(QT_ANDROID_BLUETOOTH)
- if (!d->ensureNativeSocket(service.socketProtocol())) {
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
- d->connectToService(service.device().address(), service.serviceUuid(), openMode);
-#else
-#if defined(QT_WINRT_BLUETOOTH)
- // Report these problems early:
- if (socketType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-#endif // QT_WINRT_BLUETOOTH
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService cannot "
- "connect with 'UnknownProtocol' type";
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
+/*!
+ \fn void QBluetoothSocket::connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, OpenMode mode = ReadWrite)
- if (service.protocolServiceMultiplexer() > 0) {
- if (!d->ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
- d->errorString = tr("Unknown socket error");
- setSocketError(UnknownSocketError);
- return;
- }
- d->connectToService(service.device().address(), service.protocolServiceMultiplexer(), openMode);
- } else if (service.serverChannel() > 0) {
- if (!d->ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
- d->errorString = tr("Unknown socket error");
- setSocketError(UnknownSocketError);
- return;
- }
- d->connectToService(service.device().address(), service.serverChannel(), openMode);
- } else {
- // try doing service discovery to see if we can find the socket
- if (service.serviceUuid().isNull()
- && !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
- qCWarning(QT_BT) << "No port, no PSM, and no UUID provided, unable to connect";
- return;
- }
- qCDebug(QT_BT) << "Need a port/psm, doing discovery";
- doDeviceDiscovery(service, openMode);
- }
-#endif
-}
+ \internal
+
+ Exists to avoid QTBUG-65831.
+*/
/*!
Attempts to make a connection to the service identified by \a uuid on the device with address
@@ -392,10 +371,10 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op
For BlueZ, the socket first enters the \l ServiceLookupState and queries the connection parameters for
\a uuid. If the service parameters are successfully retrieved the socket enters
ConnectingState, and attempts to connect to \a address. If a connection is established,
- QBluetoothSocket enters Connected State and emits connected().
+ QBluetoothSocket enters \l ConnectedState and emits connected().
On Android, the service connection can directly be established
- using the UUID of the remote service. Therefore the platforms does not require
+ using the UUID of the remote service. Therefore the platform does not require
the \l ServiceLookupState and \l socketType() is always set to
\l QBluetoothServiceInfo::RfcommProtocol.
@@ -408,45 +387,8 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op
*/
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode)
{
- Q_D(QBluetoothSocket);
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
- d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
- setSocketError(QBluetoothSocket::OperationError);
- return;
- }
-
-#if defined(QT_ANDROID_BLUETOOTH)
- if (!d->ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
+ Q_D(QBluetoothSocketBase);
d->connectToService(address, uuid, openMode);
-#else
-#if defined(QT_WINRT_BLUETOOTH)
- // Report these problems early, prevent device discovery:
- if (socketType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-#endif // QT_WINRT_BLUETOOTH
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService cannot "
- "connect with 'UnknownProtocol' type";
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- QBluetoothServiceInfo service;
- QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
- service.setDevice(device);
- service.setServiceUuid(uuid);
- doDeviceDiscovery(service, openMode);
-#endif
}
/*!
@@ -460,7 +402,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const
At any point, the socket can emit error() to signal that an error occurred.
On Android, a connection to a service can not be established using a port. Calling this function
- will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}
+ will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}.
Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
the connection process may fail.
@@ -469,41 +411,8 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const
*/
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode)
{
- Q_D(QBluetoothSocket);
-#if defined(QT_ANDROID_BLUETOOTH)
- Q_UNUSED(port);
- Q_UNUSED(openMode);
- Q_UNUSED(address);
- d->errorString = tr("Connecting to port is not supported");
- setSocketError(QBluetoothSocket::ServiceNotFoundError);
- qCWarning(QT_BT) << "Connecting to port is not supported";
-#else
-#if defined(QT_WINRT_BLUETOOTH)
- // Report these problems early
- if (socketType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-#endif // QT_WINRT_BLUETOOTH
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService cannot "
- "connect with 'UnknownProtocol' type";
- d->errorString = tr("Socket type not supported");
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
- d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
- setSocketError(QBluetoothSocket::OperationError);
- return;
- }
-
- setOpenMode(openMode);
+ Q_D(QBluetoothSocketBase);
d->connectToService(address, port, openMode);
-#endif
}
/*!
@@ -515,7 +424,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint1
*/
QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->socketType;
}
@@ -524,7 +433,7 @@ QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
*/
QBluetoothSocket::SocketState QBluetoothSocket::state() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->state;
}
@@ -533,7 +442,7 @@ QBluetoothSocket::SocketState QBluetoothSocket::state() const
*/
QBluetoothSocket::SocketError QBluetoothSocket::error() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->socketError;
}
@@ -542,7 +451,7 @@ QBluetoothSocket::SocketError QBluetoothSocket::error() const
*/
QString QBluetoothSocket::errorString() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->errorString;
}
@@ -575,7 +484,7 @@ QString QBluetoothSocket::errorString() const
*/
void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
if (d->secFlags != flags)
d->secFlags = flags;
}
@@ -596,7 +505,7 @@ void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags
*/
QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->secFlags;
}
@@ -605,7 +514,7 @@ QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
*/
void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
SocketState old = d->state;
d->state = state;
if(old != d->state)
@@ -625,7 +534,7 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
bool QBluetoothSocket::canReadLine() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->canReadLine();
}
@@ -634,7 +543,7 @@ bool QBluetoothSocket::canReadLine() const
*/
void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError error_)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
d->socketError = error_;
emit error(error_);
}
@@ -647,10 +556,10 @@ void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError error_)
void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
setSocketState(QBluetoothSocket::ServiceLookupState);
- qCDebug(QT_BT) << "Starting Bluetooth Socket discovery";
+ qCDebug(QT_BT) << "Starting Bluetooth service discovery";
if(d->discoveryAgent) {
d->discoveryAgent->stop();
@@ -662,8 +571,10 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O
//qDebug() << "Got agent";
- connect(d->discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
- connect(d->discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
+ connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered,
+ this, &QBluetoothSocket::serviceDiscovered);
+ connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished,
+ this, &QBluetoothSocket::discoveryFinished);
d->openMode = openMode;
@@ -684,7 +595,7 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O
void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
qCDebug(QT_BT) << "FOUND SERVICE!" << service;
if (service.protocolServiceMultiplexer() > 0 || service.serverChannel() > 0) {
connectToService(service, d->openMode);
@@ -698,7 +609,7 @@ void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
void QBluetoothSocket::discoveryFinished()
{
qCDebug(QT_BT) << "Socket discovery finished";
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
if (d->discoveryAgent){
qCDebug(QT_BT) << "Didn't find any";
d->errorString = tr("Service cannot be found");
@@ -714,7 +625,7 @@ void QBluetoothSocket::abort()
if (state() == UnconnectedState)
return;
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
setOpenMode(QIODevice::NotOpen);
if (state() == ServiceLookupState && d->discoveryAgent) {
@@ -729,6 +640,7 @@ void QBluetoothSocket::abort()
#ifndef QT_ANDROID_BLUETOOTH
//Android closes when the Java event loop comes around
setSocketState(QBluetoothSocket::UnconnectedState);
+ emit readChannelFinished();
emit disconnected();
#endif
}
@@ -740,43 +652,43 @@ void QBluetoothSocket::disconnectFromService()
QString QBluetoothSocket::localName() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->localName();
}
QBluetoothAddress QBluetoothSocket::localAddress() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->localAddress();
}
quint16 QBluetoothSocket::localPort() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->localPort();
}
QString QBluetoothSocket::peerName() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->peerName();
}
QBluetoothAddress QBluetoothSocket::peerAddress() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->peerAddress();
}
quint16 QBluetoothSocket::peerPort() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->peerPort();
}
qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
if (!data || maxSize <= 0) {
d_ptr->errorString = tr("Invalid data/data size");
@@ -789,7 +701,7 @@ qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
return d->readData(data, maxSize);
}
@@ -798,7 +710,7 @@ void QBluetoothSocket::close()
if (state() == UnconnectedState)
return;
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
setOpenMode(QIODevice::NotOpen);
if (state() == ServiceLookupState && d->discoveryAgent) {
@@ -814,6 +726,7 @@ void QBluetoothSocket::close()
#ifndef QT_ANDROID_BLUETOOTH
//Android closes when the Java event loop comes around
setSocketState(UnconnectedState);
+ emit readChannelFinished();
emit disconnected();
#endif
}
@@ -829,7 +742,7 @@ void QBluetoothSocket::close()
bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
SocketState socketState, OpenMode openMode)
{
- Q_D(QBluetoothSocket);
+ Q_D(QBluetoothSocketBase);
return d->setSocketDescriptor(socketDescriptor, socketType, socketState, openMode);
}
@@ -840,7 +753,7 @@ bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServi
int QBluetoothSocket::socketDescriptor() const
{
- Q_D(const QBluetoothSocket);
+ Q_D(const QBluetoothSocketBase);
return d->socket;
}
diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h
index 3fc2892e..cda64dff 100644
--- a/src/bluetooth/qbluetoothsocket.h
+++ b/src/bluetooth/qbluetoothsocket.h
@@ -52,15 +52,30 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_OSX_BLUETOOTH
+class QBluetoothSocketBasePrivate;
+#else
class QBluetoothSocketPrivate;
+#endif
class Q_BLUETOOTH_EXPORT QBluetoothSocket : public QIODevice
{
Q_OBJECT
+#ifndef QT_OSX_BLUETOOTH
+ Q_DECLARE_PRIVATE(QBluetoothSocketBase)
+#else
Q_DECLARE_PRIVATE(QBluetoothSocket)
+#endif
+
friend class QBluetoothServer;
friend class QBluetoothServerPrivate;
+ friend class QBluetoothSocketPrivate;
+ friend class QBluetoothSocketPrivateAndroid;
+ friend class QBluetoothSocketPrivateBluez;
+ friend class QBluetoothSocketPrivateBluezDBus;
+ friend class QBluetoothSocketPrivateDummy;
+ friend class QBluetoothSocketPrivateWinRT;
public:
@@ -106,6 +121,11 @@ public:
void connectToService(const QBluetoothServiceInfo &service, OpenMode openMode = ReadWrite);
void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode = ReadWrite);
void connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode = ReadWrite);
+ inline void connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid,
+ OpenMode mode = ReadWrite)
+ {
+ connectToService(address, QBluetoothUuid(uuid), mode);
+ }
void disconnectFromService();
//bool flush();
@@ -161,10 +181,14 @@ private Q_SLOTS:
protected:
+#ifndef QT_OSX_BLUETOOTH
+ QBluetoothSocketBasePrivate *d_ptr;
+#else
QBluetoothSocketPrivate *d_ptr;
+#endif
private:
- friend class QLowEnergyControllerPrivate;
+ friend class QLowEnergyControllerPrivateBluez;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index d0b901ae..9047bb31 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -39,8 +39,10 @@
****************************************************************************/
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_android_p.h"
#include "qbluetoothaddress.h"
+#include "qbluetoothdeviceinfo.h"
+#include "qbluetoothserviceinfo.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QThread>
#include <QtCore/QTime>
@@ -148,8 +150,8 @@ public:
{
}
- // Runs in same thread as QBluetoothSocketPrivate
- void setupWorker(QBluetoothSocketPrivate* d_ptr, const QAndroidJniObject& socketObject,
+ // Runs in same thread as QBluetoothSocketPrivateAndroid
+ void setupWorker(QBluetoothSocketPrivateAndroid* d_ptr, const QAndroidJniObject& socketObject,
const QAndroidJniObject& uuidObject, bool useFallback,
const QBluetoothUuid& qtUuid = QBluetoothUuid())
{
@@ -159,18 +161,18 @@ public:
connect(this, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &QThread::finished, this, &QObject::deleteLater);
- connect(d_ptr, &QBluetoothSocketPrivate::connectJavaSocket,
+ connect(d_ptr, &QBluetoothSocketPrivateAndroid::connectJavaSocket,
worker, &SocketConnectWorker::connectSocket);
- connect(d_ptr, &QBluetoothSocketPrivate::closeJavaSocket,
+ connect(d_ptr, &QBluetoothSocketPrivateAndroid::closeJavaSocket,
worker, &SocketConnectWorker::closeSocket);
connect(worker, &SocketConnectWorker::socketConnectDone,
- d_ptr, &QBluetoothSocketPrivate::socketConnectSuccess);
+ d_ptr, &QBluetoothSocketPrivateAndroid::socketConnectSuccess);
if (useFallback) {
connect(worker, &SocketConnectWorker::socketConnectFailed,
- d_ptr, &QBluetoothSocketPrivate::fallbackSocketConnectFailed);
+ d_ptr, &QBluetoothSocketPrivateAndroid::fallbackSocketConnectFailed);
} else {
connect(worker, &SocketConnectWorker::socketConnectFailed,
- d_ptr, &QBluetoothSocketPrivate::defaultSocketConnectFailed);
+ d_ptr, &QBluetoothSocketPrivateAndroid::defaultSocketConnectFailed);
}
workerPointer = worker;
@@ -204,16 +206,11 @@ static QBluetoothUuid reverseUuid(const QBluetoothUuid &serviceUuid)
return QBluetoothUuid(reversed);
}
-QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : socket(-1),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- state(QBluetoothSocket::UnconnectedState),
- socketError(QBluetoothSocket::NoSocketError),
- connecting(false),
- discoveryAgent(0),
- secFlags(QBluetooth::Secure),
+QBluetoothSocketPrivateAndroid::QBluetoothSocketPrivateAndroid()
+ :
inputThread(0)
{
+ secFlags = QBluetooth::Secure;
adapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
"getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
@@ -221,13 +218,13 @@ QBluetoothSocketPrivate::QBluetoothSocketPrivate()
qRegisterMetaType<QBluetoothSocket::SocketState>();
}
-QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
+QBluetoothSocketPrivateAndroid::~QBluetoothSocketPrivateAndroid()
{
if (state != QBluetoothSocket::UnconnectedState)
emit closeJavaSocket();
}
-bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+bool QBluetoothSocketPrivateAndroid::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
socketType = type;
if (socketType == QBluetoothServiceInfo::RfcommProtocol)
@@ -236,7 +233,7 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
return false;
}
-bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channel)
+bool QBluetoothSocketPrivateAndroid::fallBackConnect(QAndroidJniObject uuid, int channel)
{
qCWarning(QT_BT_ANDROID) << "Falling back to getServiceChannel() workaround.";
@@ -355,7 +352,7 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
/*
* Workaround for QTBUG-61392
*/
-bool QBluetoothSocketPrivate::fallBackReversedConnect(const QBluetoothUuid &uuid)
+bool QBluetoothSocketPrivateAndroid::fallBackReversedConnect(const QBluetoothUuid &uuid)
{
Q_Q(QBluetoothSocket);
@@ -408,31 +405,31 @@ bool QBluetoothSocketPrivate::fallBackReversedConnect(const QBluetoothUuid &uuid
}
/*
- * The call order during a connectToService() is as follows:
+ * The call order during a connectToServiceHelper() is as follows:
*
- * 1. call connectToService()
+ * 1. call connectToServiceHelper()
* 2. wait for execution of SocketConnectThread::run()
* 3. if threaded connect succeeds call socketConnectSuccess() via signals
* -> done
* 4. if threaded connect fails call defaultSocketConnectFailed() via signals
* 5. call fallBackConnect() if Android version 22 or below
- * -> Android 23+ complete failure of entire connectToService()
+ * -> Android 23+ complete failure of entire connectToServiceHelper()
* 6. call fallBackReversedConnect() if Android version 23 or above
- * -> if failure entire connectToService() fails
+ * -> if failure entire connectToServiceHelper() fails
* 7. if threaded connect on one of above fallbacks succeeds call socketConnectSuccess()
* via signals
* -> done
* 8. if threaded connect on fallback channel fails call fallbackSocketConnectFailed()
- * -> complete failure of entire connectToService()
+ * -> complete failure of entire connectToServiceHelper()
* */
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
+void QBluetoothSocketPrivateAndroid::connectToServiceHelper(const QBluetoothAddress &address,
const QBluetoothUuid &uuid,
QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
Q_UNUSED(openMode);
- qCDebug(QT_BT_ANDROID) << "connectToService()" << address.toString() << uuid.toString();
+ qCDebug(QT_BT_ANDROID) << "connectToServiceHelper()" << address.toString() << uuid.toString();
q->setSocketState(QBluetoothSocket::ConnectingState);
@@ -508,7 +505,71 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
emit connectJavaSocket();
}
-void QBluetoothSocketPrivate::socketConnectSuccess(const QAndroidJniObject &socket)
+void QBluetoothSocketPrivateAndroid::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState
+ && q->state() != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (!ensureNativeSocket(service.socketProtocol())) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.serviceUuid(), openMode);
+}
+
+void QBluetoothSocketPrivateAndroid::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService cannot "
+ "connect with 'UnknownProtocol' (type provided by given service)";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (!ensureNativeSocket(q->socketType())) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+ connectToServiceHelper(address, uuid, openMode);
+}
+
+void QBluetoothSocketPrivateAndroid::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(port);
+ Q_UNUSED(openMode);
+ Q_UNUSED(address);
+
+ Q_Q(QBluetoothSocket);
+
+ errorString = tr("Connecting to port is not supported");
+ q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
+ qCWarning(QT_BT_ANDROID) << "Connecting to port is not supported";
+}
+
+void QBluetoothSocketPrivateAndroid::socketConnectSuccess(const QAndroidJniObject &socket)
{
Q_Q(QBluetoothSocket);
QAndroidJniEnvironment env;
@@ -568,7 +629,7 @@ void QBluetoothSocketPrivate::socketConnectSuccess(const QAndroidJniObject &sock
emit q->connected();
}
-void QBluetoothSocketPrivate::defaultSocketConnectFailed(
+void QBluetoothSocketPrivateAndroid::defaultSocketConnectFailed(
const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid,
const QBluetoothUuid &qtTargetUuid)
{
@@ -597,7 +658,7 @@ void QBluetoothSocketPrivate::defaultSocketConnectFailed(
}
}
-void QBluetoothSocketPrivate::fallbackSocketConnectFailed(
+void QBluetoothSocketPrivateAndroid::fallbackSocketConnectFailed(
const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid)
{
Q_UNUSED(targetUuid);
@@ -616,7 +677,7 @@ void QBluetoothSocketPrivate::fallbackSocketConnectFailed(
q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-void QBluetoothSocketPrivate::abort()
+void QBluetoothSocketPrivateAndroid::abort()
{
if (state == QBluetoothSocket::UnconnectedState)
return;
@@ -629,7 +690,7 @@ void QBluetoothSocketPrivate::abort()
* thread because inputStream.read() throws IOException
* In turn the thread stops and throws an error which sets
* new state, error and emits relevant signals.
- * See QBluetoothSocketPrivate::inputThreadError() for details
+ * See QBluetoothSocketPrivateAndroid::inputThreadError() for details
*/
if (inputThread)
@@ -658,7 +719,7 @@ void QBluetoothSocketPrivate::abort()
}
}
-QString QBluetoothSocketPrivate::localName() const
+QString QBluetoothSocketPrivateAndroid::localName() const
{
if (adapter.isValid())
return adapter.callObjectMethod<jstring>("getName").toString();
@@ -666,7 +727,7 @@ QString QBluetoothSocketPrivate::localName() const
return QString();
}
-QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+QBluetoothAddress QBluetoothSocketPrivateAndroid::localAddress() const
{
QString result;
if (adapter.isValid())
@@ -675,13 +736,13 @@ QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
return QBluetoothAddress(result);
}
-quint16 QBluetoothSocketPrivate::localPort() const
+quint16 QBluetoothSocketPrivateAndroid::localPort() const
{
// Impossible to get channel number with current Android API (Levels 5 to 19)
return 0;
}
-QString QBluetoothSocketPrivate::peerName() const
+QString QBluetoothSocketPrivateAndroid::peerName() const
{
if (!remoteDevice.isValid())
return QString();
@@ -689,7 +750,7 @@ QString QBluetoothSocketPrivate::peerName() const
return remoteDevice.callObjectMethod("getName", "()Ljava/lang/String;").toString();
}
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+QBluetoothAddress QBluetoothSocketPrivateAndroid::peerAddress() const
{
if (!remoteDevice.isValid())
return QBluetoothAddress();
@@ -700,13 +761,13 @@ QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
return QBluetoothAddress(address);
}
-quint16 QBluetoothSocketPrivate::peerPort() const
+quint16 QBluetoothSocketPrivateAndroid::peerPort() const
{
// Impossible to get channel number with current Android API (Levels 5 to 13)
return 0;
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateAndroid::writeData(const char *data, qint64 maxSize)
{
//TODO implement buffered behavior (so far only unbuffered)
Q_Q(QBluetoothSocket);
@@ -736,7 +797,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return maxSize;
}
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateAndroid::readData(char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
if (state != QBluetoothSocket::ConnectedState || !inputThread) {
@@ -749,7 +810,7 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return inputThread->readData(data, maxSize);
}
-void QBluetoothSocketPrivate::inputThreadError(int errorCode)
+void QBluetoothSocketPrivateAndroid::inputThreadError(int errorCode)
{
Q_Q(QBluetoothSocket);
@@ -779,10 +840,11 @@ void QBluetoothSocketPrivate::inputThreadError(int errorCode)
q->setSocketState(QBluetoothSocket::UnconnectedState);
q->setOpenMode(QIODevice::NotOpen);
+ emit q->readChannelFinished();
emit q->disconnected();
}
-void QBluetoothSocketPrivate::close()
+void QBluetoothSocketPrivateAndroid::close()
{
/* This function is called by QBluetoothSocket::close and softer version
QBluetoothSocket::disconnectFromService() which difference I do not quite fully understand.
@@ -791,7 +853,7 @@ void QBluetoothSocketPrivate::close()
abort();
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateAndroid::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_UNUSED(socketDescriptor);
@@ -802,7 +864,7 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return false;
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(const QAndroidJniObject &socket, QBluetoothServiceInfo::Protocol socketType_,
+bool QBluetoothSocketPrivateAndroid::setSocketDescriptor(const QAndroidJniObject &socket, QBluetoothServiceInfo::Protocol socketType_,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
@@ -870,7 +932,7 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(const QAndroidJniObject &socke
return true;
}
-qint64 QBluetoothSocketPrivate::bytesAvailable() const
+qint64 QBluetoothSocketPrivateAndroid::bytesAvailable() const
{
//We cannot access buffer directly as it is part of different thread
if (inputThread)
@@ -879,12 +941,12 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
return 0;
}
-qint64 QBluetoothSocketPrivate::bytesToWrite() const
+qint64 QBluetoothSocketPrivateAndroid::bytesToWrite() const
{
return 0; // nothing because always unbuffered
}
-bool QBluetoothSocketPrivate::canReadLine() const
+bool QBluetoothSocketPrivateAndroid::canReadLine() const
{
// We cannot access buffer directly as it is part of different thread
if (inputThread)
diff --git a/src/bluetooth/qbluetoothsocket_android_p.h b/src/bluetooth/qbluetoothsocket_android_p.h
new file mode 100644
index 00000000..7bf42e32
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_android_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+
+#ifndef QBLUETOOTHSOCKET_ANDROID_P_H
+#define QBLUETOOTHSOCKET_ANDROID_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothsocketbase_p.h"
+
+#include <QtAndroidExtras/QAndroidJniObject>
+#include <QtCore/QPointer>
+#include "android/inputstreamthread_p.h"
+#include <jni.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBluetoothSocketPrivateAndroid final : public QBluetoothSocketBasePrivate
+{
+ Q_OBJECT
+ friend class QBluetoothServerPrivate;
+
+public:
+ QBluetoothSocketPrivateAndroid();
+ ~QBluetoothSocketPrivateAndroid() override;
+
+ //On Android we connect using the uuid not the port
+ void connectToServiceHelper(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ bool fallBackConnect(QAndroidJniObject uuid, int channel);
+ bool fallBackReversedConnect(const QBluetoothUuid &uuid);
+
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
+
+ void abort() override;
+ void close() override;
+
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+
+ bool setSocketDescriptor(const QAndroidJniObject &socket, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
+
+ QAndroidJniObject adapter;
+ QAndroidJniObject socketObject;
+ QAndroidJniObject remoteDevice;
+ QAndroidJniObject inputStream;
+ QAndroidJniObject outputStream;
+ InputStreamThread *inputThread;
+
+public slots:
+ void socketConnectSuccess(const QAndroidJniObject &socket);
+ void defaultSocketConnectFailed(const QAndroidJniObject & socket,
+ const QAndroidJniObject &targetUuid,
+ const QBluetoothUuid &qtTargetUuid);
+ void fallbackSocketConnectFailed(const QAndroidJniObject &socket,
+ const QAndroidJniObject &targetUuid);
+ void inputThreadError(int errorCode);
+
+signals:
+ void connectJavaSocket();
+ void closeJavaSocket();
+
+};
+
+// QTBUG-61392 related
+// Private API to disable the silent behavior to reverse a remote service's
+// UUID. In rare cases the workaround behavior might not be desirable as
+// it may lead to connects to incorrect services.
+extern bool useReverseUuidWorkAroundConnect;
+
+QT_END_NAMESPACE
+
+#endif // QBLUETOOTHSOCKET_ANDROID_P_H
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index 17b8e738..ccf34e7b 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -38,7 +38,8 @@
****************************************************************************/
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_bluez_p.h"
+#include "qbluetoothdeviceinfo.h"
#include "bluez/manager_p.h"
#include "bluez/adapter_p.h"
@@ -62,38 +63,30 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
-QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : socket(-1),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- state(QBluetoothSocket::UnconnectedState),
- socketError(QBluetoothSocket::NoSocketError),
- readNotifier(0),
- connectWriteNotifier(0),
- connecting(false),
- discoveryAgent(0),
- secFlags(QBluetooth::Authorization),
- lowEnergySocketType(0)
+QBluetoothSocketPrivateBluez::QBluetoothSocketPrivateBluez()
+ : QBluetoothSocketBasePrivate()
{
+ secFlags = QBluetooth::Authorization;
}
-QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
+QBluetoothSocketPrivateBluez::~QBluetoothSocketPrivateBluez()
{
delete readNotifier;
- readNotifier = 0;
+ readNotifier = nullptr;
delete connectWriteNotifier;
- connectWriteNotifier = 0;
+ connectWriteNotifier = nullptr;
}
-bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+bool QBluetoothSocketPrivateBluez::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
if (socket != -1) {
if (socketType == type)
return true;
delete readNotifier;
- readNotifier = 0;
+ readNotifier = nullptr;
delete connectWriteNotifier;
- connectWriteNotifier = 0;
+ connectWriteNotifier = nullptr;
QT_CLOSE(socket);
}
@@ -129,7 +122,7 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
return true;
}
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateBluez::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
int result = -1;
@@ -214,7 +207,111 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
}
}
-void QBluetoothSocketPrivate::_q_writeNotify()
+void QBluetoothSocketPrivateBluez::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState
+ && q->state() != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ // we are checking the service protocol and not socketType()
+ // socketType will change in ensureNativeSocket()
+ if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocket::connectToService cannot "
+ "connect with 'UnknownProtocol' (type provided by given service)";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (service.protocolServiceMultiplexer() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(),
+ openMode);
+ } else if (service.serverChannel() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
+ } else {
+ // try doing service discovery to see if we can find the socket
+ if (service.serviceUuid().isNull()
+ && !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
+ qCWarning(QT_BT_BLUEZ) << "No port, no PSM, and no UUID provided. Unable to connect";
+ return;
+ }
+ qCDebug(QT_BT_BLUEZ) << "Need a port/psm, doing discovery";
+ q->doDeviceDiscovery(service, openMode);
+ }
+}
+
+void QBluetoothSocketPrivateBluez::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot "
+ "connect with 'UnknownProtocol' (type provided by given service)";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ QBluetoothServiceInfo service;
+ QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
+ service.setDevice(device);
+ service.setServiceUuid(uuid);
+ q->doDeviceDiscovery(service, openMode);
+}
+
+void QBluetoothSocketPrivateBluez::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot "
+ "connect with 'UnknownProtocol' (type provided by given service)";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+ connectToServiceHelper(address, port, openMode);
+}
+
+void QBluetoothSocketPrivateBluez::_q_writeNotify()
{
Q_Q(QBluetoothSocket);
if(connecting && state == QBluetoothSocket::ConnectingState){
@@ -275,7 +372,7 @@ void QBluetoothSocketPrivate::_q_writeNotify()
}
}
-void QBluetoothSocketPrivate::_q_readNotify()
+void QBluetoothSocketPrivateBluez::_q_readNotify()
{
Q_Q(QBluetoothSocket);
char *writePointer = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE);
@@ -302,7 +399,7 @@ void QBluetoothSocketPrivate::_q_readNotify()
}
}
-void QBluetoothSocketPrivate::abort()
+void QBluetoothSocketPrivateBluez::abort()
{
delete readNotifier;
readNotifier = 0;
@@ -316,7 +413,7 @@ void QBluetoothSocketPrivate::abort()
socket = -1;
}
-QString QBluetoothSocketPrivate::localName() const
+QString QBluetoothSocketPrivateBluez::localName() const
{
const QBluetoothAddress address = localAddress();
if (address.isNull())
@@ -326,7 +423,7 @@ QString QBluetoothSocketPrivate::localName() const
return device.name();
}
-QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+QBluetoothAddress QBluetoothSocketPrivateBluez::localAddress() const
{
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
sockaddr_rc addr;
@@ -345,7 +442,7 @@ QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
return QBluetoothAddress();
}
-quint16 QBluetoothSocketPrivate::localPort() const
+quint16 QBluetoothSocketPrivateBluez::localPort() const
{
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
sockaddr_rc addr;
@@ -364,7 +461,7 @@ quint16 QBluetoothSocketPrivate::localPort() const
return 0;
}
-QString QBluetoothSocketPrivate::peerName() const
+QString QBluetoothSocketPrivateBluez::peerName() const
{
quint64 bdaddr;
@@ -452,7 +549,7 @@ QString QBluetoothSocketPrivate::peerName() const
}
}
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+QBluetoothAddress QBluetoothSocketPrivateBluez::peerAddress() const
{
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
sockaddr_rc addr;
@@ -471,7 +568,7 @@ QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
return QBluetoothAddress();
}
-quint16 QBluetoothSocketPrivate::peerPort() const
+quint16 QBluetoothSocketPrivateBluez::peerPort() const
{
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
sockaddr_rc addr;
@@ -490,7 +587,7 @@ quint16 QBluetoothSocketPrivate::peerPort() const
return 0;
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateBluez::writeData(const char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -535,7 +632,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
}
}
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateBluez::readData(char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -553,7 +650,7 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return 0;
}
-void QBluetoothSocketPrivate::close()
+void QBluetoothSocketPrivateBluez::close()
{
if (txBuffer.size() > 0)
connectWriteNotifier->setEnabled(true);
@@ -561,7 +658,7 @@ void QBluetoothSocketPrivate::close()
abort();
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_,
+bool QBluetoothSocketPrivateBluez::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
@@ -589,17 +686,17 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return true;
}
-qint64 QBluetoothSocketPrivate::bytesAvailable() const
+qint64 QBluetoothSocketPrivateBluez::bytesAvailable() const
{
return buffer.size();
}
-qint64 QBluetoothSocketPrivate::bytesToWrite() const
+qint64 QBluetoothSocketPrivateBluez::bytesToWrite() const
{
return txBuffer.size();
}
-bool QBluetoothSocketPrivate::canReadLine() const
+bool QBluetoothSocketPrivateBluez::canReadLine() const
{
return buffer.canReadLine();
}
diff --git a/src/bluetooth/qbluetoothsocket_bluez_p.h b/src/bluetooth/qbluetoothsocket_bluez_p.h
new file mode 100644
index 00000000..67c04b3d
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_bluez_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QBLUETOOTHSOCKET_BLUEZ_H
+#define QBLUETOOTHSOCKET_BLUEZ_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothsocketbase_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QBluetoothSocketPrivateBluez final: public QBluetoothSocketBasePrivate
+{
+ Q_OBJECT
+
+public:
+ QBluetoothSocketPrivateBluez();
+ ~QBluetoothSocketPrivateBluez() override;
+
+ void connectToServiceHelper(const QBluetoothAddress &address,
+ quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
+
+ void abort() override;
+ void close() override;
+
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
+
+private slots:
+ void _q_readNotify();
+ void _q_writeNotify();
+};
+
+QT_END_NAMESPACE
+
+#endif // QBLUETOOTHSOCKET_BLUEZ_H
diff --git a/src/bluetooth/qbluetoothsocket_p.cpp b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
index 39d483d6..bdcc89ef 100644
--- a/src/bluetooth/qbluetoothsocket_p.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -38,77 +38,89 @@
****************************************************************************/
#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
-#ifndef QT_IOS_BLUETOOTH
-#include "dummy/dummy_helper_p.h"
-#endif
+#include "qbluetoothsocket_bluezdbus_p.h"
QT_BEGIN_NAMESPACE
-
-QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : socket(-1),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- state(QBluetoothSocket::UnconnectedState),
- socketError(QBluetoothSocket::NoSocketError),
- secFlags(QBluetooth::NoSecurity)
+QBluetoothSocketPrivateBluezDBus::QBluetoothSocketPrivateBluezDBus()
{
-#ifndef QT_IOS_BLUETOOTH
- printDummyWarning();
-#endif
+ secFlags = QBluetooth::NoSecurity;
}
-QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
+QBluetoothSocketPrivateBluezDBus::~QBluetoothSocketPrivateBluezDBus()
{
}
-bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+bool QBluetoothSocketPrivateBluezDBus::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
socketType = type;
return false;
}
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateBluezDBus::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
Q_UNUSED(openMode);
Q_UNUSED(address);
Q_UNUSED(port);
}
-void QBluetoothSocketPrivate::abort()
+void QBluetoothSocketPrivateBluezDBus::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
{
+ Q_UNUSED(openMode);
+ Q_UNUSED(service);
}
-QString QBluetoothSocketPrivate::localName() const
+void QBluetoothSocketPrivateBluezDBus::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(openMode);
+ Q_UNUSED(address);
+ Q_UNUSED(uuid);
+}
+
+void QBluetoothSocketPrivateBluezDBus::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(openMode);
+ Q_UNUSED(address);
+ Q_UNUSED(port);
+}
+
+void QBluetoothSocketPrivateBluezDBus::abort()
+{
+}
+
+QString QBluetoothSocketPrivateBluezDBus::localName() const
{
return QString();
}
-QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+QBluetoothAddress QBluetoothSocketPrivateBluezDBus::localAddress() const
{
return QBluetoothAddress();
}
-quint16 QBluetoothSocketPrivate::localPort() const
+quint16 QBluetoothSocketPrivateBluezDBus::localPort() const
{
return 0;
}
-QString QBluetoothSocketPrivate::peerName() const
+QString QBluetoothSocketPrivateBluezDBus::peerName() const
{
return QString();
}
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+QBluetoothAddress QBluetoothSocketPrivateBluezDBus::peerAddress() const
{
return QBluetoothAddress();
}
-quint16 QBluetoothSocketPrivate::peerPort() const
+quint16 QBluetoothSocketPrivateBluezDBus::peerPort() const
{
return 0;
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateBluezDBus::writeData(const char *data, qint64 maxSize)
{
Q_UNUSED(data);
Q_UNUSED(maxSize);
@@ -123,7 +135,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return -1;
}
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateBluezDBus::readData(char *data, qint64 maxSize)
{
Q_UNUSED(data);
Q_UNUSED(maxSize);
@@ -139,11 +151,11 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return -1;
}
-void QBluetoothSocketPrivate::close()
+void QBluetoothSocketPrivateBluezDBus::close()
{
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateBluezDBus::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_UNUSED(socketDescriptor);
@@ -153,19 +165,18 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return false;
}
-qint64 QBluetoothSocketPrivate::bytesAvailable() const
+qint64 QBluetoothSocketPrivateBluezDBus::bytesAvailable() const
{
return 0;
}
-bool QBluetoothSocketPrivate::canReadLine() const
+bool QBluetoothSocketPrivateBluezDBus::canReadLine() const
{
return false;
}
-qint64 QBluetoothSocketPrivate::bytesToWrite() const
+qint64 QBluetoothSocketPrivateBluezDBus::bytesToWrite() const
{
return 0;
}
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_bluezdbus_p.h b/src/bluetooth/qbluetoothsocket_bluezdbus_p.h
new file mode 100644
index 00000000..c7279555
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_bluezdbus_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QBLUETOOTHSOCKET_BLUEZDBUS_H
+#define QBLUETOOTHSOCKET_BLUEZDBUS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothsocketbase_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QBluetoothSocketPrivateBluezDBus final: public QBluetoothSocketBasePrivate
+{
+ Q_OBJECT
+
+public:
+ QBluetoothSocketPrivateBluezDBus();
+ ~QBluetoothSocketPrivateBluezDBus() override;
+
+ void connectToServiceHelper(const QBluetoothAddress &address,
+ quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
+
+ void abort() override;
+ void close() override;
+
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBLUETOOTHSOCKET_BLUEZDBUS_H
diff --git a/src/bluetooth/qbluetoothsocket_dummy.cpp b/src/bluetooth/qbluetoothsocket_dummy.cpp
new file mode 100644
index 00000000..82da46c2
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_dummy.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** 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: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 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 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.
+**
+** 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 "qbluetoothsocket.h"
+#include "qbluetoothsocket_dummy_p.h"
+#ifndef QT_IOS_BLUETOOTH
+#include "dummy/dummy_helper_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QBluetoothSocketPrivateDummy::QBluetoothSocketPrivateDummy()
+{
+ secFlags = QBluetooth::NoSecurity;
+#ifndef QT_IOS_BLUETOOTH
+ printDummyWarning();
+#endif
+}
+
+QBluetoothSocketPrivateDummy::~QBluetoothSocketPrivateDummy()
+{
+}
+
+bool QBluetoothSocketPrivateDummy::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+{
+ socketType = type;
+ return false;
+}
+
+void QBluetoothSocketPrivateDummy::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(openMode);
+ Q_UNUSED(address);
+ Q_UNUSED(port);
+}
+
+void QBluetoothSocketPrivateDummy::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(service);
+ Q_UNUSED(openMode);
+
+ Q_Q(QBluetoothSocket);
+
+ qWarning() << "Using non-functional QBluetoothSocketPrivateDummy";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+}
+
+void QBluetoothSocketPrivateDummy::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(address);
+ Q_UNUSED(uuid);
+ Q_UNUSED(openMode);
+
+ Q_Q(QBluetoothSocket);
+
+ qWarning() << "Using non-functional QBluetoothSocketPrivateDummy";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+}
+
+void QBluetoothSocketPrivateDummy::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(address);
+ Q_UNUSED(port);
+ Q_UNUSED(openMode);
+
+ Q_Q(QBluetoothSocket);
+
+ qWarning() << "Using non-functional QBluetoothSocketPrivateDummy";
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+}
+
+void QBluetoothSocketPrivateDummy::abort()
+{
+}
+
+QString QBluetoothSocketPrivateDummy::localName() const
+{
+ return QString();
+}
+
+QBluetoothAddress QBluetoothSocketPrivateDummy::localAddress() const
+{
+ return QBluetoothAddress();
+}
+
+quint16 QBluetoothSocketPrivateDummy::localPort() const
+{
+ return 0;
+}
+
+QString QBluetoothSocketPrivateDummy::peerName() const
+{
+ return QString();
+}
+
+QBluetoothAddress QBluetoothSocketPrivateDummy::peerAddress() const
+{
+ return QBluetoothAddress();
+}
+
+quint16 QBluetoothSocketPrivateDummy::peerPort() const
+{
+ return 0;
+}
+
+qint64 QBluetoothSocketPrivateDummy::writeData(const char *data, qint64 maxSize)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxSize);
+
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+ return -1;
+}
+
+qint64 QBluetoothSocketPrivateDummy::readData(char *data, qint64 maxSize)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxSize);
+
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot read while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ return -1;
+}
+
+void QBluetoothSocketPrivateDummy::close()
+{
+}
+
+bool QBluetoothSocketPrivateDummy::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
+{
+ Q_UNUSED(socketDescriptor);
+ Q_UNUSED(socketType)
+ Q_UNUSED(socketState);
+ Q_UNUSED(openMode);
+ return false;
+}
+
+qint64 QBluetoothSocketPrivateDummy::bytesAvailable() const
+{
+ return 0;
+}
+
+bool QBluetoothSocketPrivateDummy::canReadLine() const
+{
+ return false;
+}
+
+qint64 QBluetoothSocketPrivateDummy::bytesToWrite() const
+{
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_dummy_p.h b/src/bluetooth/qbluetoothsocket_dummy_p.h
new file mode 100644
index 00000000..23bed109
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_dummy_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QBLUETOOTHSOCKET_DUMMY_H
+#define QBLUETOOTHSOCKET_DUMMY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothsocket.h"
+#include "qbluetoothsocketbase_p.h"
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+class QBluetoothSocketPrivateDummy final : public QBluetoothSocketBasePrivate
+{
+ Q_OBJECT
+ friend class QBluetoothServerPrivate;
+
+public:
+ QBluetoothSocketPrivateDummy();
+ ~QBluetoothSocketPrivateDummy() override;
+
+ void connectToServiceHelper(const QBluetoothAddress &address,
+ quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
+
+ void abort() override;
+ void close() override;
+
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
+};
+
+QT_END_NAMESPACE // QBLUETOOTHSOCKET_DUMMY_H
+
+#endif
diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm
index de7e2120..ea39bb39 100644
--- a/src/bluetooth/qbluetoothsocket_osx.mm
+++ b/src/bluetooth/qbluetoothsocket_osx.mm
@@ -41,9 +41,7 @@
// The order is important (the first header contains
// the base class for a private socket) - workaround for
// dependencies problem.
-#include "qbluetoothsocket_p.h"
-#include "qbluetoothsocket_osx_p.h"
-//
+#include "qbluetoothsocketbase_p.h"
#include "qbluetoothsocket_osx_p.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothdeviceinfo.h"
@@ -60,14 +58,14 @@
QT_BEGIN_NAMESPACE
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : q_ptr(nullptr),
- writeChunk(std::numeric_limits<UInt16>::max()),
+ : writeChunk(std::numeric_limits<UInt16>::max()),
openMode(QIODevice::NotOpen), // That's what is set in public class' ctors.
state(QBluetoothSocket::UnconnectedState),
socketType(QBluetoothServiceInfo::UnknownProtocol),
socketError(QBluetoothSocket::NoSocketError),
isConnecting(false)
{
+ q_ptr = nullptr;
}
QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
@@ -351,6 +349,7 @@ void QBluetoothSocketPrivate::channelClosed()
if (!isConnecting) {
q_ptr->setSocketState(QBluetoothSocket::UnconnectedState);
q_ptr->setOpenMode(QIODevice::NotOpen);
+ emit q_ptr->readChannelFinished();
emit q_ptr->disconnected();
} else {
state = QBluetoothSocket::UnconnectedState;
@@ -638,6 +637,7 @@ void QBluetoothSocket::abort()
d_ptr->abort();
setSocketState(QBluetoothSocket::UnconnectedState);
+ emit readChannelFinished();
emit disconnected();
}
@@ -726,6 +726,7 @@ void QBluetoothSocket::close()
d_ptr->close();
setSocketState(UnconnectedState);
+ emit readChannelFinished();
emit disconnected();
}
diff --git a/src/bluetooth/qbluetoothsocket_osx_p.h b/src/bluetooth/qbluetoothsocket_osx_p.h
index ce376702..dcc684b8 100644
--- a/src/bluetooth/qbluetoothsocket_osx_p.h
+++ b/src/bluetooth/qbluetoothsocket_osx_p.h
@@ -79,10 +79,9 @@
QT_BEGIN_NAMESPACE
-class QBluetoothServiceDiscoveryAgent;
class QBluetoothAddress;
-class QBluetoothSocketPrivate : public QBluetoothSocketPrivateBase, public OSXBluetooth::ChannelDelegate
+class QBluetoothSocketPrivate : public QBluetoothSocketBasePrivate, public OSXBluetooth::ChannelDelegate
{
friend class QBluetoothSocket;
friend class QBluetoothServer;
@@ -121,8 +120,6 @@ private:
qint64 writeData(const char *data, qint64 maxSize);
qint64 readData(char *data, qint64 maxSize);
- QBluetoothSocket *q_ptr;
-
QScopedPointer<QBluetoothServiceDiscoveryAgent> discoveryAgent;
QPrivateLinearBuffer buffer;
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index ec511974..556d9fc5 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -37,8 +37,7 @@
**
****************************************************************************/
-#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_winrt_p.h"
#ifdef CLASSIC_APP_BUILD
#define Q_OS_WINRT
@@ -48,6 +47,8 @@
#include <private/qeventdispatcher_winrt_p.h>
#include <QtBluetooth/QBluetoothLocalDevice>
+#include <QtBluetooth/qbluetoothdeviceinfo.h>
+#include <QtBluetooth/qbluetoothserviceinfo.h>
#include <QtCore/qloggingcategory.h>
#include <robuffer.h>
@@ -129,7 +130,12 @@ public:
~SocketWorker()
{
+ }
+ void close()
+ {
+ m_shuttingDown = true;
if (Q_UNLIKELY(m_initialReadOp)) {
+ onReadyRead(m_initialReadOp.Get(), Canceled);
ComPtr<IAsyncInfo> info;
HRESULT hr = m_initialReadOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -139,9 +145,11 @@ public:
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
+ m_initialReadOp.Reset();
}
if (m_readOp) {
+ onReadyRead(m_readOp.Get(), Canceled);
ComPtr<IAsyncInfo> info;
HRESULT hr = m_readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -151,6 +159,7 @@ public:
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
+ m_readOp.Reset();
}
}
@@ -190,6 +199,9 @@ public:
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
+ if (m_shuttingDown)
+ return S_OK;
+
if (asyncInfo == m_initialReadOp.Get()) {
m_initialReadOp.Reset();
} else if (asyncInfo == m_readOp.Get()) {
@@ -299,6 +311,7 @@ public:
private:
ComPtr<IStreamSocket> m_socket;
QVector<QByteArray> m_pendingData;
+ bool m_shuttingDown = false;
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex m_mutex;
@@ -307,26 +320,22 @@ private:
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> m_readOp;
};
-QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : socket(-1),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- state(QBluetoothSocket::UnconnectedState),
- socketError(QBluetoothSocket::NoSocketError),
- secFlags(QBluetooth::NoSecurity),
- m_worker(new SocketWorker())
+QBluetoothSocketPrivateWinRT::QBluetoothSocketPrivateWinRT()
+ : m_worker(new SocketWorker())
{
+ secFlags = QBluetooth::NoSecurity;
connect(m_worker, &SocketWorker::newDataReceived,
- this, &QBluetoothSocketPrivate::handleNewData, Qt::QueuedConnection);
+ this, &QBluetoothSocketPrivateWinRT::handleNewData, Qt::QueuedConnection);
connect(m_worker, &SocketWorker::socketErrorOccured,
- this, &QBluetoothSocketPrivate::handleError, Qt::QueuedConnection);
+ this, &QBluetoothSocketPrivateWinRT::handleError, Qt::QueuedConnection);
}
-QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
+QBluetoothSocketPrivateWinRT::~QBluetoothSocketPrivateWinRT()
{
abort();
}
-bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+bool QBluetoothSocketPrivateWinRT::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
if (socket != -1) {
if (type == socketType)
@@ -350,7 +359,7 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
return true;
}
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
Q_UNUSED(openMode);
@@ -369,14 +378,14 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> remoteHost;
hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
- RETURN_VOID_IF_FAILED("QBluetoothSocketPrivate::connectToService: Could not create hostname.");
+ RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
const QString portString = QString::number(port);
HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
hr = m_socketObject->ConnectAsync(remoteHost.Get(), portReference.Get(), &m_connectOp);
if (hr == E_ACCESSDENIED) {
- qErrnoWarning(hr, "QBluetoothSocketPrivate::connectToService: Unable to connect to bluetooth socket."
+ qErrnoWarning(hr, "QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket."
"Please check your manifest capabilities.");
q->setSocketState(QBluetoothSocket::UnconnectedState);
return;
@@ -388,22 +397,120 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
QEventDispatcherWinRT::runOnXamlThread([this]() {
HRESULT hr;
hr = m_connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
- this, &QBluetoothSocketPrivate::handleConnectOpFinished).Get());
+ this, &QBluetoothSocketPrivateWinRT::handleConnectOpFinished).Get());
RETURN_HR_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback");
return S_OK;
});
}
-void QBluetoothSocketPrivate::abort()
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState
+ && q->state() != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocket::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ // we are checking the service protocol and not socketType()
+ // socketType will change in ensureNativeSocket()
+ if (service.socketProtocol() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (service.protocolServiceMultiplexer() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), openMode);
+ } else if (service.serverChannel() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
+ } else {
+ // try doing service discovery to see if we can find the socket
+ if (service.serviceUuid().isNull()
+ && !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
+ qCWarning(QT_BT_WINRT) << "No port, no PSM, and no UUID provided. Unable to connect";
+ return;
+ }
+ qCDebug(QT_BT_WINRT) << "Need a port/psm, doing discovery";
+ q->doDeviceDiscovery(service, openMode);
+ }
+}
+
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ QBluetoothServiceInfo service;
+ QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
+ service.setDevice(device);
+ service.setServiceUuid(uuid);
+ q->doDeviceDiscovery(service, openMode);
+}
+
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ connectToServiceHelper(address, port, openMode);
+}
+
+void QBluetoothSocketPrivateWinRT::abort()
{
Q_Q(QBluetoothSocket);
if (state == QBluetoothSocket::UnconnectedState)
return;
disconnect(m_worker, &SocketWorker::newDataReceived,
- this, &QBluetoothSocketPrivate::handleNewData);
+ this, &QBluetoothSocketPrivateWinRT::handleNewData);
disconnect(m_worker, &SocketWorker::socketErrorOccured,
- this, &QBluetoothSocketPrivate::handleError);
+ this, &QBluetoothSocketPrivateWinRT::handleError);
+ m_worker->close();
m_worker->deleteLater();
if (socket != -1) {
@@ -413,7 +520,7 @@ void QBluetoothSocketPrivate::abort()
q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-QString QBluetoothSocketPrivate::localName() const
+QString QBluetoothSocketPrivateWinRT::localName() const
{
const QBluetoothAddress address = localAddress();
if (address.isNull())
@@ -423,7 +530,7 @@ QString QBluetoothSocketPrivate::localName() const
return device.name();
}
-QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+QBluetoothAddress QBluetoothSocketPrivateWinRT::localAddress() const
{
if (!m_socketObject)
return QBluetoothAddress();
@@ -441,7 +548,7 @@ QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
return QBluetoothAddress(qt_QStringFromHString(localAddress));
}
-quint16 QBluetoothSocketPrivate::localPort() const
+quint16 QBluetoothSocketPrivateWinRT::localPort() const
{
if (!m_socketObject)
return 0;
@@ -456,7 +563,7 @@ quint16 QBluetoothSocketPrivate::localPort() const
return qt_QStringFromHString(localPortString).toInt();
}
-QString QBluetoothSocketPrivate::peerName() const
+QString QBluetoothSocketPrivateWinRT::peerName() const
{
if (!m_socketObject)
return QString();
@@ -474,7 +581,7 @@ QString QBluetoothSocketPrivate::peerName() const
return qt_QStringFromHString(remoteHostName);
}
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+QBluetoothAddress QBluetoothSocketPrivateWinRT::peerAddress() const
{
if (!m_socketObject)
return QBluetoothAddress();
@@ -492,7 +599,7 @@ QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
return QBluetoothAddress(qt_QStringFromHString(remoteAddress));
}
-quint16 QBluetoothSocketPrivate::peerPort() const
+quint16 QBluetoothSocketPrivateWinRT::peerPort() const
{
if (!m_socketObject)
return 0;
@@ -507,7 +614,7 @@ quint16 QBluetoothSocketPrivate::peerPort() const
return qt_QStringFromHString(remotePortString).toInt();
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateWinRT::writeData(const char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -533,7 +640,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return bytesWritten;
}
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateWinRT::readData(char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -549,12 +656,12 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return 0;
}
-void QBluetoothSocketPrivate::close()
+void QBluetoothSocketPrivateWinRT::close()
{
abort();
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_UNUSED(socketDescriptor);
@@ -565,7 +672,7 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return false;
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(ComPtr<IStreamSocket> socketPtr, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(ComPtr<IStreamSocket> socketPtr, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
@@ -582,22 +689,22 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(ComPtr<IStreamSocket> socketPt
return true;
}
-qint64 QBluetoothSocketPrivate::bytesAvailable() const
+qint64 QBluetoothSocketPrivateWinRT::bytesAvailable() const
{
return buffer.size();
}
-qint64 QBluetoothSocketPrivate::bytesToWrite() const
+qint64 QBluetoothSocketPrivateWinRT::bytesToWrite() const
{
return 0; // nothing because always unbuffered
}
-bool QBluetoothSocketPrivate::canReadLine() const
+bool QBluetoothSocketPrivateWinRT::canReadLine() const
{
return buffer.canReadLine();
}
-void QBluetoothSocketPrivate::handleNewData(const QVector<QByteArray> &data)
+void QBluetoothSocketPrivateWinRT::handleNewData(const QVector<QByteArray> &data)
{
// Defer putting the data into the list until the next event loop iteration
// (where the readyRead signal is emitted as well)
@@ -605,7 +712,7 @@ void QBluetoothSocketPrivate::handleNewData(const QVector<QByteArray> &data)
Q_ARG(QVector<QByteArray>, data));
}
-void QBluetoothSocketPrivate::handleError(QBluetoothSocket::SocketError error)
+void QBluetoothSocketPrivateWinRT::handleError(QBluetoothSocket::SocketError error)
{
Q_Q(QBluetoothSocket);
switch (error) {
@@ -623,7 +730,7 @@ void QBluetoothSocketPrivate::handleError(QBluetoothSocket::SocketError error)
q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-void QBluetoothSocketPrivate::addToPendingData(const QVector<QByteArray> &data)
+void QBluetoothSocketPrivateWinRT::addToPendingData(const QVector<QByteArray> &data)
{
Q_Q(QBluetoothSocket);
QMutexLocker locker(&m_readMutex);
@@ -636,7 +743,7 @@ void QBluetoothSocketPrivate::addToPendingData(const QVector<QByteArray> &data)
emit q->readyRead();
}
-HRESULT QBluetoothSocketPrivate::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status)
+HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status)
{
Q_Q(QBluetoothSocket);
if (status != Completed || !m_connectOp) { // Protect against a late callback
diff --git a/src/bluetooth/qbluetoothsocket_winrt_p.h b/src/bluetooth/qbluetoothsocket_winrt_p.h
new file mode 100644
index 00000000..6a740206
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocket_winrt_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QBLUETOOTHSOCKET_WINRT_P_H
+#define QBLUETOOTHSOCKET_WINRT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothsocket.h"
+#include "qbluetoothsocketbase_p.h"
+#include <QtGlobal>
+
+QT_FORWARD_DECLARE_CLASS(SocketWorker)
+
+QT_BEGIN_NAMESPACE
+
+class QBluetoothSocketPrivateWinRT final: public QBluetoothSocketBasePrivate
+{
+ Q_OBJECT
+ friend class QBluetoothServerPrivate;
+
+public:
+ QBluetoothSocketPrivateWinRT();
+ ~QBluetoothSocketPrivateWinRT() override;
+
+ void connectToServiceHelper(const QBluetoothAddress &address,
+ quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) override;
+ void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) override;
+
+ bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override;
+
+ QString localName() const override;
+ QBluetoothAddress localAddress() const override;
+ quint16 localPort() const override;
+
+ QString peerName() const override;
+ QBluetoothAddress peerAddress() const override;
+ quint16 peerPort() const override;
+
+ void abort() override;
+ void close() override;
+
+ qint64 writeData(const char *data, qint64 maxSize) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+
+ bool setSocketDescriptor(Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> socket,
+ QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override;
+
+ qint64 bytesAvailable() const override;
+ bool canReadLine() const override;
+ qint64 bytesToWrite() const override;
+
+ SocketWorker *m_worker;
+
+ Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> m_socketObject;
+ Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> m_connectOp;
+
+ QMutex m_readMutex;
+
+ // Protected by m_readMutex. Written in addToPendingData (native callback)
+ QVector<QByteArray> m_pendingData;
+
+ Q_INVOKABLE void addToPendingData(const QVector<QByteArray> &data);
+
+private slots:
+ void handleNewData(const QVector<QByteArray> &data);
+ void handleError(QBluetoothSocket::SocketError error);
+
+private:
+ HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action,
+ ABI::Windows::Foundation::AsyncStatus status);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/bluetooth/qbluetoothsocketbase.cpp b/src/bluetooth/qbluetoothsocketbase.cpp
new file mode 100644
index 00000000..8401a1c3
--- /dev/null
+++ b/src/bluetooth/qbluetoothsocketbase.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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: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 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 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.
+**
+** 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 "qbluetoothsocketbase_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QBluetoothSocketBasePrivate::QBluetoothSocketBasePrivate(QObject *parent) : QObject(parent)
+{
+
+}
+
+QBluetoothSocketBasePrivate::~QBluetoothSocketBasePrivate()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocketbase_p.h
index 907acbe2..410dcbbd 100644
--- a/src/bluetooth/qbluetoothsocket_p.h
+++ b/src/bluetooth/qbluetoothsocketbase_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QBLUETOOTHSOCKET_P_H
-#define QBLUETOOTHSOCKET_P_H
+#ifndef QBLUETOOTHSOCKETBASEPRIVATE_P_H
+#define QBLUETOOTHSOCKETBASEPRIVATE_P_H
//
// W A R N I N G
@@ -51,17 +51,17 @@
// We mean it.
//
-#include "qbluetoothsocket.h"
+#include <qglobal.h>
+#include <QObject>
+#include <QtBluetooth/qbluetoothsocket.h>
-#ifdef QT_ANDROID_BLUETOOTH
+#if defined(QT_ANDROID_BLUETOOTH)
#include <QtAndroidExtras/QAndroidJniObject>
-#include <QtCore/QPointer>
-#include "android/inputstreamthread_p.h"
-#include <jni.h>
-class WorkerThread;
#endif
-#ifdef QT_WINRT_BLUETOOTH
+#if defined(QT_WINRT_BLUETOOTH)
+#include <QtCore/QMutex>
+
#include <wrl.h>
namespace ABI {
@@ -84,191 +84,97 @@ namespace ABI {
#endif
#include "qprivatelinearbuffer_p.h"
-#include <QtGlobal>
-
QT_FORWARD_DECLARE_CLASS(QSocketNotifier)
+QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent)
QT_BEGIN_NAMESPACE
-#ifdef QT_WINRT_BLUETOOTH
-class SocketWorker;
-#endif
-
-class QBluetoothServiceDiscoveryAgent;
-
-class QSocketServerPrivate
-{
-public:
- QSocketServerPrivate();
- ~QSocketServerPrivate();
-};
-
-
-
-class QBluetoothSocket;
-class QBluetoothServiceDiscoveryAgent;
-
#ifndef QT_OSX_BLUETOOTH
-class QBluetoothSocketPrivate : public QObject
+class QBluetoothSocketBasePrivate : public QObject
{
Q_OBJECT
- Q_DECLARE_PUBLIC(QBluetoothSocket)
- friend class QBluetoothServerPrivate;
public:
+ explicit QBluetoothSocketBasePrivate(QObject *parent = nullptr);
+ virtual ~QBluetoothSocketBasePrivate();
- QBluetoothSocketPrivate();
- ~QBluetoothSocketPrivate();
+ virtual bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) = 0;
-//On Android we connect using the uuid not the port
-#if defined(QT_ANDROID_BLUETOOTH)
- void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
- QIODevice::OpenMode openMode);
-#else
- void connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode);
-#endif
-#ifdef QT_ANDROID_BLUETOOTH
- bool fallBackConnect(QAndroidJniObject uuid, int channel);
- bool fallBackReversedConnect(const QBluetoothUuid &uuid);
-#endif
+ virtual QString localName() const = 0;
+ virtual QBluetoothAddress localAddress() const = 0;
+ virtual quint16 localPort() const = 0;
+ virtual QString peerName() const = 0;
+ virtual QBluetoothAddress peerAddress() const = 0;
+ virtual quint16 peerPort() const = 0;
- bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type);
+ virtual void abort() = 0;
+ virtual void close() = 0;
- QString localName() const;
- QBluetoothAddress localAddress() const;
- quint16 localPort() const;
+ virtual qint64 writeData(const char *data, qint64 maxSize) = 0;
+ virtual qint64 readData(char *data, qint64 maxSize) = 0;
- QString peerName() const;
- QBluetoothAddress peerAddress() const;
- quint16 peerPort() const;
- //QBluetoothServiceInfo peerService() const;
+ virtual qint64 bytesAvailable() const = 0;
+ virtual bool canReadLine() const = 0;
+ virtual qint64 bytesToWrite() const = 0;
- void abort();
- void close();
+ virtual bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0;
- //qint64 readBufferSize() const;
- //void setReadBufferSize(qint64 size);
- qint64 writeData(const char *data, qint64 maxSize);
- qint64 readData(char *data, qint64 maxSize);
+#if defined(QT_ANDROID_BLUETOOTH)
+ virtual void connectToServiceHelper(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) = 0;
+#else
+ virtual void connectToServiceHelper(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) = 0;
+#endif
+ virtual void connectToService(const QBluetoothServiceInfo &service,
+ QIODevice::OpenMode openMode) = 0;
+ virtual void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode) = 0;
+ virtual void connectToService(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode) = 0;
#ifdef QT_ANDROID_BLUETOOTH
- bool setSocketDescriptor(const QAndroidJniObject &socket, QBluetoothServiceInfo::Protocol socketType,
+ virtual bool setSocketDescriptor(const QAndroidJniObject &socket, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
- QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite);
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0;
#elif defined(QT_WINRT_BLUETOOTH)
- bool setSocketDescriptor(Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> socket,
+ virtual bool setSocketDescriptor(Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> socket,
QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
- QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite);
+ QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0;
#endif
- bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
- QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
- QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite);
-
- qint64 bytesAvailable() const;
- bool canReadLine() const;
- qint64 bytesToWrite() const;
public:
QPrivateLinearBuffer buffer;
QPrivateLinearBuffer txBuffer;
- int socket;
- QBluetoothServiceInfo::Protocol socketType;
- QBluetoothSocket::SocketState state;
- QBluetoothSocket::SocketError socketError;
- QSocketNotifier *readNotifier;
- QSocketNotifier *connectWriteNotifier;
- bool connecting;
-
- QBluetoothServiceDiscoveryAgent *discoveryAgent;
+ int socket = -1;
+ QBluetoothServiceInfo::Protocol socketType = QBluetoothServiceInfo::UnknownProtocol;
+ QBluetoothSocket::SocketState state = QBluetoothSocket::UnconnectedState;
+ QBluetoothSocket::SocketError socketError = QBluetoothSocket::NoSocketError;
+ QSocketNotifier *readNotifier = nullptr;
+ QSocketNotifier *connectWriteNotifier = nullptr;
+ bool connecting = false;
+
+ QBluetoothServiceDiscoveryAgent *discoveryAgent = nullptr;
QBluetoothSocket::OpenMode openMode;
QBluetooth::SecurityFlags secFlags;
-
-// QByteArray rxBuffer;
-// qint64 rxOffset;
QString errorString;
-#ifdef QT_ANDROID_BLUETOOTH
- QAndroidJniObject adapter;
- QAndroidJniObject socketObject;
- QAndroidJniObject remoteDevice;
- QAndroidJniObject inputStream;
- QAndroidJniObject outputStream;
- InputStreamThread *inputThread;
-
-public slots:
- void socketConnectSuccess(const QAndroidJniObject &socket);
- void defaultSocketConnectFailed(const QAndroidJniObject & socket,
- const QAndroidJniObject &targetUuid,
- const QBluetoothUuid &qtTargetUuid);
- void fallbackSocketConnectFailed(const QAndroidJniObject &socket,
- const QAndroidJniObject &targetUuid);
- void inputThreadError(int errorCode);
-
-signals:
- void connectJavaSocket();
- void closeJavaSocket();
-
-#endif
-
-#ifdef QT_WINRT_BLUETOOTH
- SocketWorker *m_worker;
-
- Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocket> m_socketObject;
- Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> m_connectOp;
-
- QMutex m_readMutex;
-
- // Protected by m_readMutex. Written in addToPendingData (native callback)
- QVector<QByteArray> m_pendingData;
-
- Q_INVOKABLE void addToPendingData(const QVector<QByteArray> &data);
-
-private slots:
- void handleNewData(const QVector<QByteArray> &data);
- void handleError(QBluetoothSocket::SocketError error);
-#endif // QT_WINRT_BLUETOOTH
-
-#if QT_CONFIG(bluez)
-private slots:
- void _q_readNotify();
- void _q_writeNotify();
-#endif
-
protected:
+ Q_DECLARE_PUBLIC(QBluetoothSocket)
QBluetoothSocket *q_ptr;
-private:
-
-#ifdef QT_WINRT_BLUETOOTH
- HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status);
-#endif
-
#if QT_CONFIG(bluez)
public:
- quint8 lowEnergySocketType;
+ quint8 lowEnergySocketType = 0;
#endif
};
-#else // QT_OSX_BLUETOOTH
-
-// QBluetoothSocketPrivate on OS X can not contain
-// Q_OBJECT (moc does not parse Objective-C syntax).
-// But QBluetoothSocket still requires QMetaObject::invokeMethod
-// to work. Here's the trick:
-class QBluetoothSocketPrivateBase : public QObject
-{
-// The most important part of it:
- Q_OBJECT
-public slots:
- virtual void _q_writeNotify() = 0;
-};
-
-#endif // QT_OSX_BLUETOOTH
-
static inline void convertAddress(const quint64 from, quint8 (&to)[6])
{
to[0] = (from >> 0) & 0xff;
@@ -279,7 +185,7 @@ static inline void convertAddress(const quint64 from, quint8 (&to)[6])
to[5] = (from >> 40) & 0xff;
}
-static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = 0)
+static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = nullptr)
{
const quint64 result = (quint64(from[0]) << 0) |
(quint64(from[1]) << 8) |
@@ -292,16 +198,26 @@ static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = 0)
return result;
}
-#ifdef Q_OS_ANDROID
-// QTBUG-61392 related
-// Private API to disable the silent behavior to reverse a remote service's
-// UUID. In rare cases the workaround behavior might not be desirable as
-// it may lead to connects to incorrect services.
-extern bool useReverseUuidWorkAroundConnect;
+#else // QT_OSX_BLUETOOTH
-#endif
+// QBluetoothSocketPrivate on macOS can not contain
+// Q_OBJECT (moc does not parse Objective-C syntax).
+// But QBluetoothSocket still requires QMetaObject::invokeMethod
+// to work. Here's the trick:
+class QBluetoothSocketBasePrivate : public QObject
+{
+// The most important part of it:
+ Q_OBJECT
+public slots:
+ virtual void _q_writeNotify() = 0;
-QT_END_NAMESPACE
+protected:
+ Q_DECLARE_PUBLIC(QBluetoothSocket)
+ QBluetoothSocket *q_ptr;
+};
+#endif // QT_OSX_BLUETOOTH
-#endif
+QT_END_NAMESPACE
+
+#endif // QBLUETOOTHSOCKETBASE_P_H
diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h
index 28b08583..25c7896c 100644
--- a/src/bluetooth/qbluetoothuuid.h
+++ b/src/bluetooth/qbluetoothuuid.h
@@ -58,6 +58,7 @@ struct quint128
class Q_BLUETOOTH_EXPORT QBluetoothUuid : public QUuid
{
public:
+ //TODO Qt 6: Convert enums to scoped enums (see QTBUG-65831)
enum ProtocolUuid {
Sdp = 0x0001,
Udp = 0x0002,
@@ -381,6 +382,8 @@ public:
bool operator==(const QBluetoothUuid &other) const;
bool operator!=(const QBluetoothUuid &other) const { return !operator==(other); }
+ QBluetoothUuid &operator=(const QBluetoothUuid &other) = default;
+
int minimumSize() const;
quint16 toUInt16(bool *ok = nullptr) const;
diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp
index b964f620..bff5a590 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -41,7 +41,7 @@
#include "bluez/bluez_data_p.h"
#include "bluez/hcimanager_p.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocketbase_p.h"
#include <QtCore/qloggingcategory.h>
diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h
index 154c9936..f870a582 100644
--- a/src/bluetooth/qlowenergycharacteristic.h
+++ b/src/bluetooth/qlowenergycharacteristic.h
@@ -97,7 +97,12 @@ protected:
friend class QLowEnergyService;
friend class QLowEnergyControllerPrivate;
+ friend class QLowEnergyControllerPrivateAndroid;
+ friend class QLowEnergyControllerPrivateBluez;
+ friend class QLowEnergyControllerPrivateBluezDBus;
+ friend class QLowEnergyControllerPrivateCommon;
friend class QLowEnergyControllerPrivateOSX;
+ friend class QLowEnergyControllerPrivateWinRT;
QLowEnergyCharacteristicPrivate *data;
QLowEnergyCharacteristic(QSharedPointer<QLowEnergyServicePrivate> p,
QLowEnergyHandle handle);
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 7cd80072..6b4c17d6 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qlowenergycontroller.h"
-#include "qlowenergycontroller_p.h"
#include "qlowenergycharacteristicdata.h"
#include "qlowenergyconnectionparameters.h"
@@ -48,6 +47,19 @@
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtCore/QLoggingCategory>
+
+#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
+#include "bluez/bluez5_helper_p.h"
+#include "qlowenergycontroller_bluezdbus_p.h"
+#include "qlowenergycontroller_bluez_p.h"
+#elif defined(QT_ANDROID_BLUETOOTH)
+#include "qlowenergycontroller_android_p.h"
+#elif defined(QT_WINRT_BLUETOOTH)
+#include "qlowenergycontroller_winrt_p.h"
+#else
+#include "qlowenergycontroller_p.h"
+#endif
+
#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -274,212 +286,35 @@ void registerQLowEnergyControllerMetaType()
qRegisterMetaType<QLowEnergyController::ControllerState>();
qRegisterMetaType<QLowEnergyController::Error>();
qRegisterMetaType<QLowEnergyConnectionParameters>();
+ qRegisterMetaType<QLowEnergyCharacteristic>();
+ qRegisterMetaType<QLowEnergyDescriptor>();
initDone = true;
}
}
-
-void QLowEnergyControllerPrivate::setError(
- QLowEnergyController::Error newError)
+static QLowEnergyControllerPrivate *privateController(QLowEnergyController::Role role)
{
- Q_Q(QLowEnergyController);
- error = newError;
-
- switch (newError) {
- case QLowEnergyController::UnknownRemoteDeviceError:
- errorString = QLowEnergyController::tr("Remote device cannot be found");
- break;
- case QLowEnergyController::InvalidBluetoothAdapterError:
- errorString = QLowEnergyController::tr("Cannot find local adapter");
- break;
- case QLowEnergyController::NetworkError:
- errorString = QLowEnergyController::tr("Error occurred during connection I/O");
- break;
- case QLowEnergyController::ConnectionError:
- errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device.");
- break;
- case QLowEnergyController::AdvertisingError:
- errorString = QLowEnergyController::tr("Error occurred trying to start advertising");
- break;
- case QLowEnergyController::RemoteHostClosedError:
- errorString = QLowEnergyController::tr("Remote device closed the connection");
- break;
- case QLowEnergyController::NoError:
- return;
- default:
- case QLowEnergyController::UnknownError:
- errorString = QLowEnergyController::tr("Unknown Error");
- break;
+#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
+ // The new DBUS implementation only supports Central role for now
+ // For Peripheral role support see QTBUG-66909
+ if (role == QLowEnergyController::CentralRole
+ && bluetoothdVersion() >= QVersionNumber(5, 42)) {
+ qCWarning(QT_BT) << "Using BlueZ LE DBus API";
+ return new QLowEnergyControllerPrivateBluezDBus();
+ } else {
+ qCWarning(QT_BT) << "Using BlueZ kernel ATT interface";
+ return new QLowEnergyControllerPrivateBluez();
}
-
- emit q->error(newError);
-}
-
-bool QLowEnergyControllerPrivate::isValidLocalAdapter()
-{
-#ifdef QT_WINRT_BLUETOOTH
- return true;
+#elif defined(QT_ANDROID_BLUETOOTH)
+ Q_UNUSED(role);
+ return new QLowEnergyControllerPrivateAndroid();
+#elif defined(QT_WINRT_BLUETOOTH)
+ Q_UNUSED(role);
+ return new QLowEnergyControllerPrivateWinRT();
+#else
+ Q_UNUSED(role);
+ return new QLowEnergyControllerPrivateCommon();
#endif
- if (localAdapter.isNull())
- return false;
-
- const QList<QBluetoothHostInfo> foundAdapters = QBluetoothLocalDevice::allDevices();
- bool adapterFound = false;
-
- foreach (const QBluetoothHostInfo &info, foundAdapters) {
- if (info.address() == localAdapter) {
- adapterFound = true;
- break;
- }
- }
-
- return adapterFound;
-}
-
-void QLowEnergyControllerPrivate::setState(
- QLowEnergyController::ControllerState newState)
-{
- Q_Q(QLowEnergyController);
- if (state == newState)
- return;
-
- state = newState;
- if (state == QLowEnergyController::UnconnectedState
- && role == QLowEnergyController::PeripheralRole) {
- remoteDevice.clear();
- }
- emit q->stateChanged(state);
-}
-
-void QLowEnergyControllerPrivate::invalidateServices()
-{
- foreach (const QSharedPointer<QLowEnergyServicePrivate> service, serviceList.values()) {
- service->setController(0);
- service->setState(QLowEnergyService::InvalidService);
- }
-
- serviceList.clear();
-}
-
-QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivate::serviceForHandle(
- QLowEnergyHandle handle)
-{
- ServiceDataMap &currentList = serviceList;
- if (role == QLowEnergyController::PeripheralRole)
- currentList = localServices;
-
- const QList<QSharedPointer<QLowEnergyServicePrivate>> values = currentList.values();
- for (auto service: values)
- if (service->startHandle <= handle && handle <= service->endHandle)
- return service;
-
- return QSharedPointer<QLowEnergyServicePrivate>();
-}
-
-/*!
- Returns a valid characteristic if the given handle is the
- handle of the characteristic itself or one of its descriptors
- */
-QLowEnergyCharacteristic QLowEnergyControllerPrivate::characteristicForHandle(
- QLowEnergyHandle handle)
-{
- QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(handle);
- if (service.isNull())
- return QLowEnergyCharacteristic();
-
- if (service->characteristicList.isEmpty())
- return QLowEnergyCharacteristic();
-
- // check whether it is the handle of a characteristic header
- if (service->characteristicList.contains(handle))
- return QLowEnergyCharacteristic(service, handle);
-
- // check whether it is the handle of the characteristic value or its descriptors
- QList<QLowEnergyHandle> charHandles = service->characteristicList.keys();
- std::sort(charHandles.begin(), charHandles.end());
- for (int i = charHandles.size() - 1; i >= 0; i--) {
- if (charHandles.at(i) > handle)
- continue;
-
- return QLowEnergyCharacteristic(service, charHandles.at(i));
- }
-
- return QLowEnergyCharacteristic();
-}
-
-/*!
- Returns a valid descriptor if \a handle belongs to a descriptor;
- otherwise an invalid one.
- */
-QLowEnergyDescriptor QLowEnergyControllerPrivate::descriptorForHandle(
- QLowEnergyHandle handle)
-{
- const QLowEnergyCharacteristic matchingChar = characteristicForHandle(handle);
- if (!matchingChar.isValid())
- return QLowEnergyDescriptor();
-
- const QLowEnergyServicePrivate::CharData charData = matchingChar.
- d_ptr->characteristicList[matchingChar.attributeHandle()];
-
- if (charData.descriptorList.contains(handle))
- return QLowEnergyDescriptor(matchingChar.d_ptr, matchingChar.attributeHandle(),
- handle);
-
- return QLowEnergyDescriptor();
-}
-
-/*!
- Returns the length of the updated characteristic value.
- */
-quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic(
- QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue)
-{
- QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
- if (!service.isNull()) {
- CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle);
- if (charIt != service->characteristicList.end()) {
- QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
-
- if (appendValue)
- charDetails.value += value;
- else
- charDetails.value = value;
-
- return charDetails.value.size();
- }
- }
-
- return 0;
-}
-
-/*!
- Returns the length of the updated descriptor value.
- */
-quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor(
- QLowEnergyHandle charHandle, QLowEnergyHandle descriptorHandle,
- const QByteArray &value, bool appendValue)
-{
- QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
- if (!service.isNull()) {
- CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle);
- if (charIt != service->characteristicList.end()) {
- QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
-
- DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle);
- if (descIt != charDetails.descriptorList.end()) {
- QLowEnergyServicePrivate::DescData &descDetails = descIt.value();
-
- if (appendValue)
- descDetails.value += value;
- else
- descDetails.value = value;
-
- return descDetails.value.size();
- }
- }
- }
-
- return 0;
}
/*!
@@ -497,8 +332,10 @@ quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor(
QLowEnergyController::QLowEnergyController(
const QBluetoothAddress &remoteDevice,
QObject *parent)
- : QObject(parent), d_ptr(new QLowEnergyControllerPrivate())
+ : QObject(parent)
{
+ d_ptr = privateController(CentralRole);
+
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = CentralRole;
@@ -524,8 +361,10 @@ QLowEnergyController::QLowEnergyController(
QLowEnergyController::QLowEnergyController(
const QBluetoothDeviceInfo &remoteDeviceInfo,
QObject *parent)
- : QObject(parent), d_ptr(new QLowEnergyControllerPrivate())
+ : QObject(parent)
{
+ d_ptr = privateController(CentralRole);
+
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = CentralRole;
@@ -555,8 +394,10 @@ QLowEnergyController::QLowEnergyController(
const QBluetoothAddress &remoteDevice,
const QBluetoothAddress &localDevice,
QObject *parent)
- : QObject(parent), d_ptr(new QLowEnergyControllerPrivate())
+ : QObject(parent)
{
+ d_ptr = privateController(CentralRole);
+
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = CentralRole;
@@ -598,8 +439,10 @@ QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent)
}
QLowEnergyController::QLowEnergyController(QObject *parent)
- : QObject(parent), d_ptr(new QLowEnergyControllerPrivate())
+ : QObject(parent)
{
+ d_ptr = privateController(PeripheralRole);
+
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = PeripheralRole;
@@ -760,9 +603,10 @@ void QLowEnergyController::connectToDevice()
This function does nothing if the controller is in the \l UnconnectedState.
- If the controller is in the peripheral role, it stops advertising too.
- The application must restart the advertising mode by calling
- \l startAdvertising().
+ If the controller is in the peripheral role, it stops advertising and removes
+ all services which have previously been added via \l addService().
+ To reuse the QLowEnergyController instance the application must re-add services
+ and restart the advertising mode by calling \l startAdvertising().
\sa connectToDevice()
*/
@@ -899,6 +743,9 @@ void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameter
/*!
Stops advertising, if this object is currently in the advertising state.
+ The controller has to be in the \l PeripheralRole for this function to work.
+ It does not invalidate services which have previously been added via \l addService().
+
\since 5.7
\sa startAdvertising()
*/
@@ -917,8 +764,15 @@ void QLowEnergyController::stopAdvertising()
The controller must be in the \l PeripheralRole and in the \l UnconnectedState. The \a service
object must be valid.
+ \note Once the peripheral instance is disconnected from the remote central device or
+ if \l disconnectFromDevice() is manually called, every service definition that was
+ previously added via this function is removed from the peripheral. Therefore this function
+ must be called again before re-advertising this peripheral controller instance. The described
+ behavior is connection specific and therefore not dependent on whether \l stopAdvertising()
+ was called.
+
\since 5.7
- \sa QLowEnergyServiceData::addIncludedService
+ \sa stopAdvertising(), disconnectFromDevice(), QLowEnergyServiceData::addIncludedService
*/
QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData &service,
QObject *parent)
@@ -944,55 +798,6 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
return newService;
}
-QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper(
- const QLowEnergyServiceData &service)
-{
- // Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit).
- // Since this is not mandatory, we ignore it here and let the caller take responsibility
- // for it.
-
- const auto servicePrivate = QSharedPointer<QLowEnergyServicePrivate>::create();
- servicePrivate->state = QLowEnergyService::LocalService;
- servicePrivate->setController(this);
- servicePrivate->uuid = service.uuid();
- servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary
- ? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService;
- foreach (QLowEnergyService * const includedService, service.includedServices()) {
- servicePrivate->includedServices << includedService->serviceUuid();
- includedService->d_ptr->type |= QLowEnergyService::IncludedService;
- }
-
- // Spec v4.2, Vol 3, Part G, Section 3.
- const QLowEnergyHandle oldLastHandle = this->lastLocalHandle;
- servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration.
- this->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations.
- foreach (const QLowEnergyCharacteristicData &cd, service.characteristics()) {
- const QLowEnergyHandle declHandle = ++this->lastLocalHandle;
- QLowEnergyServicePrivate::CharData charData;
- charData.valueHandle = ++this->lastLocalHandle;
- charData.uuid = cd.uuid();
- charData.properties = cd.properties();
- charData.value = cd.value();
- foreach (const QLowEnergyDescriptorData &dd, cd.descriptors()) {
- QLowEnergyServicePrivate::DescData descData;
- descData.uuid = dd.uuid();
- descData.value = dd.value();
- charData.descriptorList.insert(++this->lastLocalHandle, descData);
- }
- servicePrivate->characteristicList.insert(declHandle, charData);
- }
- servicePrivate->endHandle = this->lastLocalHandle;
- const bool handleOverflow = this->lastLocalHandle <= oldLastHandle;
- if (handleOverflow) {
- qCWarning(QT_BT) << "Not enough attribute handles left to create this service";
- this->lastLocalHandle = oldLastHandle;
- return nullptr;
- }
-
- this->localServices.insert(servicePrivate->uuid, servicePrivate);
- this->addToGenericAttributeList(service, servicePrivate->startHandle);
- return new QLowEnergyService(servicePrivate);
-}
/*!
Requests the controller to update the connection according to \a parameters.
diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp
index a1decd96..54665f7b 100644
--- a/src/bluetooth/qlowenergycontroller_android.cpp
+++ b/src/bluetooth/qlowenergycontroller_android.cpp
@@ -37,9 +37,10 @@
**
****************************************************************************/
-#include "qlowenergycontroller_p.h"
+#include "qlowenergycontroller_android_p.h"
#include <QtCore/QLoggingCategory>
#include <QtAndroidExtras/QAndroidJniEnvironment>
+#include <QtAndroidExtras/QAndroidJniObject>
#include <QtBluetooth/QLowEnergyServiceData>
#include <QtBluetooth/QLowEnergyCharacteristicData>
#include <QtBluetooth/QLowEnergyDescriptorData>
@@ -69,16 +70,14 @@ static QAndroidJniObject javaUuidfromQtUuid(const QBluetoothUuid& uuid)
return javaUuid;
}
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
- : QObject(),
- state(QLowEnergyController::UnconnectedState),
- error(QLowEnergyController::NoError),
+QLowEnergyControllerPrivateAndroid::QLowEnergyControllerPrivateAndroid()
+ : QLowEnergyControllerPrivate(),
hub(0)
{
registerQLowEnergyControllerMetaType();
}
-QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivateAndroid::~QLowEnergyControllerPrivateAndroid()
{
if (role == QLowEnergyController::PeripheralRole) {
if (hub)
@@ -86,7 +85,7 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
}
}
-void QLowEnergyControllerPrivate::init()
+void QLowEnergyControllerPrivateAndroid::init()
{
// Android Central/Client support starts with v18
// Peripheral/Server support requires Android API v21
@@ -106,13 +105,13 @@ void QLowEnergyControllerPrivate::init()
// we only connect to the peripheral role specific signals
// TODO add connections as they get added later on
connect(hub, &LowEnergyNotificationHub::connectionUpdated,
- this, &QLowEnergyControllerPrivate::connectionUpdated);
+ this, &QLowEnergyControllerPrivateAndroid::connectionUpdated);
connect(hub, &LowEnergyNotificationHub::advertisementError,
- this, &QLowEnergyControllerPrivate::advertisementError);
+ this, &QLowEnergyControllerPrivateAndroid::advertisementError);
connect(hub, &LowEnergyNotificationHub::serverCharacteristicChanged,
- this, &QLowEnergyControllerPrivate::serverCharacteristicChanged);
+ this, &QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged);
connect(hub, &LowEnergyNotificationHub::serverDescriptorWritten,
- this, &QLowEnergyControllerPrivate::serverDescriptorWritten);
+ this, &QLowEnergyControllerPrivateAndroid::serverDescriptorWritten);
} else {
if (version < 18) {
qWarning() << "Qt Bluetooth LE Central/Client support not available"
@@ -123,25 +122,25 @@ void QLowEnergyControllerPrivate::init()
hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this);
// we only connect to the central role specific signals
connect(hub, &LowEnergyNotificationHub::connectionUpdated,
- this, &QLowEnergyControllerPrivate::connectionUpdated);
+ this, &QLowEnergyControllerPrivateAndroid::connectionUpdated);
connect(hub, &LowEnergyNotificationHub::servicesDiscovered,
- this, &QLowEnergyControllerPrivate::servicesDiscovered);
+ this, &QLowEnergyControllerPrivateAndroid::servicesDiscovered);
connect(hub, &LowEnergyNotificationHub::serviceDetailsDiscoveryFinished,
- this, &QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished);
+ this, &QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished);
connect(hub, &LowEnergyNotificationHub::characteristicRead,
- this, &QLowEnergyControllerPrivate::characteristicRead);
+ this, &QLowEnergyControllerPrivateAndroid::characteristicRead);
connect(hub, &LowEnergyNotificationHub::descriptorRead,
- this, &QLowEnergyControllerPrivate::descriptorRead);
+ this, &QLowEnergyControllerPrivateAndroid::descriptorRead);
connect(hub, &LowEnergyNotificationHub::characteristicWritten,
- this, &QLowEnergyControllerPrivate::characteristicWritten);
+ this, &QLowEnergyControllerPrivateAndroid::characteristicWritten);
connect(hub, &LowEnergyNotificationHub::descriptorWritten,
- this, &QLowEnergyControllerPrivate::descriptorWritten);
+ this, &QLowEnergyControllerPrivateAndroid::descriptorWritten);
connect(hub, &LowEnergyNotificationHub::characteristicChanged,
- this, &QLowEnergyControllerPrivate::characteristicChanged);
+ this, &QLowEnergyControllerPrivateAndroid::characteristicChanged);
}
}
-void QLowEnergyControllerPrivate::connectToDevice()
+void QLowEnergyControllerPrivateAndroid::connectToDevice()
{
if (!hub)
return; // Android version below v18
@@ -170,7 +169,7 @@ void QLowEnergyControllerPrivate::connectToDevice()
}
}
-void QLowEnergyControllerPrivate::disconnectFromDevice()
+void QLowEnergyControllerPrivateAndroid::disconnectFromDevice()
{
/* Catch an Android timeout bug. If the device is connecting but cannot
* physically connect it seems to ignore the disconnect call below.
@@ -181,14 +180,18 @@ void QLowEnergyControllerPrivate::disconnectFromDevice()
QLowEnergyController::ControllerState oldState = state;
setState(QLowEnergyController::ClosingState);
- if (hub)
- hub->javaObject().callMethod<void>("disconnect");
+ if (hub) {
+ if (role == QLowEnergyController::PeripheralRole)
+ hub->javaObject().callMethod<void>("disconnectServer");
+ else
+ hub->javaObject().callMethod<void>("disconnect");
+ }
if (oldState == QLowEnergyController::ConnectingState)
setState(QLowEnergyController::UnconnectedState);
}
-void QLowEnergyControllerPrivate::discoverServices()
+void QLowEnergyControllerPrivateAndroid::discoverServices()
{
if (hub && hub->javaObject().callMethod<jboolean>("discoverServices")) {
qCDebug(QT_BT_ANDROID) << "Service discovery initiated";
@@ -199,7 +202,7 @@ void QLowEnergyControllerPrivate::discoverServices()
}
}
-void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service)
+void QLowEnergyControllerPrivateAndroid::discoverServiceDetails(const QBluetoothUuid &service)
{
if (!serviceList.contains(service)) {
qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString()
@@ -234,7 +237,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s
qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started";
}
-void QLowEnergyControllerPrivate::writeCharacteristic(
+void QLowEnergyControllerPrivateAndroid::writeCharacteristic(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QByteArray &newValue,
@@ -288,7 +291,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(
service->setError(QLowEnergyService::CharacteristicWriteError);
}
-void QLowEnergyControllerPrivate::writeDescriptor(
+void QLowEnergyControllerPrivateAndroid::writeDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descHandle,
@@ -339,7 +342,7 @@ void QLowEnergyControllerPrivate::writeDescriptor(
service->setError(QLowEnergyService::DescriptorWriteError);
}
-void QLowEnergyControllerPrivate::readCharacteristic(
+void QLowEnergyControllerPrivateAndroid::readCharacteristic(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle)
{
@@ -367,7 +370,7 @@ void QLowEnergyControllerPrivate::readCharacteristic(
service->setError(QLowEnergyService::CharacteristicReadError);
}
-void QLowEnergyControllerPrivate::readDescriptor(
+void QLowEnergyControllerPrivateAndroid::readDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle /*charHandle*/,
const QLowEnergyHandle descriptorHandle)
@@ -393,7 +396,7 @@ void QLowEnergyControllerPrivate::readDescriptor(
service->setError(QLowEnergyService::DescriptorReadError);
}
-void QLowEnergyControllerPrivate::connectionUpdated(
+void QLowEnergyControllerPrivateAndroid::connectionUpdated(
QLowEnergyController::ControllerState newState,
QLowEnergyController::Error errorCode)
{
@@ -409,7 +412,7 @@ void QLowEnergyControllerPrivate::connectionUpdated(
}
// called if server/peripheral
-void QLowEnergyControllerPrivate::peripheralConnectionUpdated(
+void QLowEnergyControllerPrivateAndroid::peripheralConnectionUpdated(
QLowEnergyController::ControllerState newState,
QLowEnergyController::Error errorCode)
{
@@ -431,15 +434,21 @@ void QLowEnergyControllerPrivate::peripheralConnectionUpdated(
Q_Q(QLowEnergyController);
if (oldState == QLowEnergyController::ConnectedState
&& newState != QLowEnergyController::ConnectedState) {
+ remoteDevice.clear();
+ remoteName.clear();
emit q->disconnected();
} else if (newState == QLowEnergyController::ConnectedState
&& oldState != QLowEnergyController::ConnectedState) {
+ if (hub) {
+ remoteDevice = QBluetoothAddress(hub->javaObject().callObjectMethod<jstring>("remoteAddress").toString());
+ remoteName = hub->javaObject().callObjectMethod<jstring>("remoteName").toString();
+ }
emit q->connected();
}
}
// called if client/central
-void QLowEnergyControllerPrivate::centralConnectionUpdated(
+void QLowEnergyControllerPrivateAndroid::centralConnectionUpdated(
QLowEnergyController::ControllerState newState,
QLowEnergyController::Error errorCode)
{
@@ -484,7 +493,7 @@ void QLowEnergyControllerPrivate::centralConnectionUpdated(
}
}
-void QLowEnergyControllerPrivate::servicesDiscovered(
+void QLowEnergyControllerPrivateAndroid::servicesDiscovered(
QLowEnergyController::Error errorCode, const QString &foundServices)
{
Q_Q(QLowEnergyController);
@@ -515,7 +524,7 @@ void QLowEnergyControllerPrivate::servicesDiscovered(
}
}
-void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished(
+void QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished(
const QString &serviceUuid, int startHandle, int endHandle)
{
const QBluetoothUuid service(serviceUuid);
@@ -563,7 +572,7 @@ void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished(
pointer->setState(QLowEnergyService::ServiceDiscovered);
}
-void QLowEnergyControllerPrivate::characteristicRead(
+void QLowEnergyControllerPrivateAndroid::characteristicRead(
const QBluetoothUuid &serviceUuid, int handle,
const QBluetoothUuid &charUuid, int properties, const QByteArray &data)
{
@@ -594,7 +603,7 @@ void QLowEnergyControllerPrivate::characteristicRead(
}
}
-void QLowEnergyControllerPrivate::descriptorRead(
+void QLowEnergyControllerPrivateAndroid::descriptorRead(
const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
int descHandle, const QBluetoothUuid &descUuid, const QByteArray &data)
{
@@ -635,7 +644,7 @@ void QLowEnergyControllerPrivate::descriptorRead(
}
}
-void QLowEnergyControllerPrivate::characteristicWritten(
+void QLowEnergyControllerPrivateAndroid::characteristicWritten(
int charHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode)
{
QSharedPointer<QLowEnergyServicePrivate> service =
@@ -664,7 +673,7 @@ void QLowEnergyControllerPrivate::characteristicWritten(
emit service->characteristicWritten(characteristic, data);
}
-void QLowEnergyControllerPrivate::descriptorWritten(
+void QLowEnergyControllerPrivateAndroid::descriptorWritten(
int descHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode)
{
QSharedPointer<QLowEnergyServicePrivate> service =
@@ -691,7 +700,7 @@ void QLowEnergyControllerPrivate::descriptorWritten(
emit service->descriptorWritten(descriptor, data);
}
-void QLowEnergyControllerPrivate::serverDescriptorWritten(
+void QLowEnergyControllerPrivateAndroid::serverDescriptorWritten(
const QAndroidJniObject &jniDesc, const QByteArray &newValue)
{
qCDebug(QT_BT_ANDROID) << "Server descriptor change notification" << newValue.toHex();
@@ -756,7 +765,7 @@ void QLowEnergyControllerPrivate::serverDescriptorWritten(
}
}
-void QLowEnergyControllerPrivate::characteristicChanged(
+void QLowEnergyControllerPrivateAndroid::characteristicChanged(
int charHandle, const QByteArray &data)
{
QSharedPointer<QLowEnergyServicePrivate> service =
@@ -781,7 +790,7 @@ void QLowEnergyControllerPrivate::characteristicChanged(
emit service->characteristicChanged(characteristic, data);
}
-void QLowEnergyControllerPrivate::serverCharacteristicChanged(
+void QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged(
const QAndroidJniObject &characteristic, const QByteArray &newValue)
{
qCDebug(QT_BT_ANDROID) << "Server characteristic change notification" << newValue.toHex();
@@ -830,7 +839,7 @@ void QLowEnergyControllerPrivate::serverCharacteristicChanged(
QLowEnergyCharacteristic(servicePrivate, foundHandle), newValue);
}
-void QLowEnergyControllerPrivate::serviceError(
+void QLowEnergyControllerPrivateAndroid::serviceError(
int attributeHandle, QLowEnergyService::ServiceError errorCode)
{
// ignore call if it isn't really an error
@@ -846,7 +855,7 @@ void QLowEnergyControllerPrivate::serviceError(
service->setError(errorCode);
}
-void QLowEnergyControllerPrivate::advertisementError(int errorCode)
+void QLowEnergyControllerPrivateAndroid::advertisementError(int errorCode)
{
Q_Q(QLowEnergyController);
@@ -997,7 +1006,7 @@ static QAndroidJniObject createJavaAdvertiseSettings(const QLowEnergyAdvertising
}
-void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &params,
+void QLowEnergyControllerPrivateAndroid::startAdvertising(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
const QLowEnergyAdvertisingData &scanResponseData)
{
@@ -1024,13 +1033,13 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa
}
}
-void QLowEnergyControllerPrivate::stopAdvertising()
+void QLowEnergyControllerPrivateAndroid::stopAdvertising()
{
setState(QLowEnergyController::UnconnectedState);
hub->javaObject().callMethod<void>("stopAdvertising");
}
-void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
+void QLowEnergyControllerPrivateAndroid::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
{
// Possible since Android v21
// Android does not permit specification of specific latency or min/max
@@ -1169,7 +1178,7 @@ static int setupDescPermissions(const QLowEnergyDescriptorData &descData)
return permissions;
}
-void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &serviceData,
+void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEnergyServiceData &serviceData,
QLowEnergyHandle startHandle)
{
QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(startHandle);
diff --git a/src/bluetooth/qlowenergycontroller_android_p.h b/src/bluetooth/qlowenergycontroller_android_p.h
new file mode 100644
index 00000000..3f97e363
--- /dev/null
+++ b/src/bluetooth/qlowenergycontroller_android_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QLOWENERGYCONTROLLERPRIVATEANDROID_P_H
+#define QLOWENERGYCONTROLLERPRIVATEANDROID_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <qglobal.h>
+#include <QtCore/QQueue>
+#include <QtCore/QVector>
+#include <QtBluetooth/qbluetooth.h>
+#include <QtBluetooth/qlowenergycharacteristic.h>
+#include "qlowenergycontroller.h"
+#include "qlowenergycontrollerbase_p.h"
+
+#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
+#include <QtBluetooth/QBluetoothSocket>
+#elif defined(QT_ANDROID_BLUETOOTH)
+#include <QtAndroidExtras/QAndroidJniObject>
+#include "android/lowenergynotificationhub_p.h"
+#elif defined(QT_WINRT_BLUETOOTH)
+#include <wrl.h>
+#include <windows.devices.bluetooth.h>
+#endif
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyServiceData;
+class QTimer;
+
+#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
+class HciManager;
+class LeCmacCalculator;
+class QSocketNotifier;
+class RemoteDeviceManager;
+#elif defined(QT_ANDROID_BLUETOOTH)
+class LowEnergyNotificationHub;
+#elif defined(QT_WINRT_BLUETOOTH)
+class QWinRTLowEnergyServiceHandler;
+#endif
+
+extern void registerQLowEnergyControllerMetaType();
+
+class QLeAdvertiser;
+
+class QLowEnergyControllerPrivateAndroid final : public QLowEnergyControllerPrivate
+{
+ Q_OBJECT
+public:
+ QLowEnergyControllerPrivateAndroid();
+ ~QLowEnergyControllerPrivateAndroid() override;
+
+ void init() override;
+
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &service) override;
+
+ void startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising() override;
+
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
+
+ // read data
+ void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle) override;
+ void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle) override;
+
+ // write data
+ void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QByteArray &newValue, QLowEnergyService::WriteMode mode) override;
+ void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue) override;
+
+ void addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle) override;
+
+private:
+
+ LowEnergyNotificationHub *hub;
+
+private slots:
+ void connectionUpdated(QLowEnergyController::ControllerState newState,
+ QLowEnergyController::Error errorCode);
+ void servicesDiscovered(QLowEnergyController::Error errorCode,
+ const QString &foundServices);
+ void serviceDetailsDiscoveryFinished(const QString& serviceUuid,
+ int startHandle, int endHandle);
+ void characteristicRead(const QBluetoothUuid &serviceUuid, int handle,
+ const QBluetoothUuid &charUuid, int properties,
+ const QByteArray& data);
+ void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
+ int handle, const QBluetoothUuid &descUuid, const QByteArray &data);
+ void characteristicWritten(int charHandle, const QByteArray &data,
+ QLowEnergyService::ServiceError errorCode);
+ void descriptorWritten(int descHandle, const QByteArray &data,
+ QLowEnergyService::ServiceError errorCode);
+ void serverDescriptorWritten(const QAndroidJniObject &jniDesc, const QByteArray &newValue);
+ void characteristicChanged(int charHandle, const QByteArray &data);
+ void serverCharacteristicChanged(const QAndroidJniObject &jniChar, const QByteArray &newValue);
+ void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode);
+ void advertisementError(int errorCode);
+
+private:
+ void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState,
+ QLowEnergyController::Error errorCode);
+ void centralConnectionUpdated(QLowEnergyController::ControllerState newState,
+ QLowEnergyController::Error errorCode);
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOWENERGYCONTROLLERPRIVATEANDROID_P_H
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index ca3f7760..502f42ad 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -39,15 +39,21 @@
****************************************************************************/
#include "lecmaccalculator_p.h"
-#include "qlowenergycontroller_p.h"
-#include "qbluetoothsocket_p.h"
+#include "qlowenergycontroller_bluez_p.h"
+#include "qbluetoothsocketbase_p.h"
#include "qleadvertiser_p.h"
#include "bluez/bluez_data_p.h"
#include "bluez/hcimanager_p.h"
+#include "bluez/objectmanager_p.h"
#include "bluez/remotedevicemanager_p.h"
#include "bluez/bluez5_helper_p.h"
#include "bluez/bluetoothmanagement_p.h"
+// Bluez 4
+#include "bluez/adapter_p.h"
+#include "bluez/device_p.h"
+#include "bluez/manager_p.h"
+
#include <QtCore/QFileInfo>
#include <QtCore/QLoggingCategory>
#include <QtCore/QSettings>
@@ -263,11 +269,8 @@ template<> void putDataAndIncrement(const QByteArray &value, char *&dst)
dst += value.count();
}
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
- : QObject(),
- state(QLowEnergyController::UnconnectedState),
- error(QLowEnergyController::NoError),
- lastLocalHandle(0),
+QLowEnergyControllerPrivateBluez::QLowEnergyControllerPrivateBluez()
+ : QLowEnergyControllerPrivate(),
l2cpSocket(0), requestPending(false),
mtuSize(ATT_DEFAULT_LE_MTU),
securityLevelValue(-1),
@@ -280,7 +283,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
qRegisterMetaType<QList<QLowEnergyHandle> >();
}
-void QLowEnergyControllerPrivate::init()
+void QLowEnergyControllerPrivateBluez::init()
{
hciManager = new HciManager(localAdapter, this);
if (!hciManager->isValid())
@@ -331,12 +334,12 @@ void QLowEnergyControllerPrivate::init()
requestTimer->setSingleShot(true);
requestTimer->setInterval(gattRequestTimeout);
connect(requestTimer, &QTimer::timeout,
- this, &QLowEnergyControllerPrivate::handleGattRequestTimeout);
+ this, &QLowEnergyControllerPrivateBluez::handleGattRequestTimeout);
}
}
}
-void QLowEnergyControllerPrivate::handleGattRequestTimeout()
+void QLowEnergyControllerPrivateBluez::handleGattRequestTimeout()
{
// antyhing open that might require cancellation or a warning?
if (encryptionChangePending) {
@@ -346,8 +349,8 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout()
}
if (!openRequests.isEmpty() && requestPending) {
- requestPending = false; // reset pending flag
const Request currentRequest = openRequests.dequeue();
+ requestPending = false; // reset pending flag
qCWarning(QT_BT_BLUEZ).nospace() << "****** Request type 0x" << hex << currentRequest.command
<< " to server/peripheral timed out";
@@ -372,7 +375,6 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout()
case ATT_OP_EXCHANGE_MTU_REQUEST: // MTU change request
// never received reply to MTU request
// it is safe to skip and go to next request
- sendNextPendingRequest();
break;
case ATT_OP_READ_BY_GROUP_REQUEST: // primary or secondary service discovery
case ATT_OP_READ_BY_TYPE_REQUEST: // characteristic or included service discovery
@@ -406,12 +408,17 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout()
break;
default:
// not a command used by central role implementation
- return;
+ qCWarning(QT_BT_BLUEZ) << "Missing response for ATT peripheral command: "
+ << hex << command;
+ break;
}
+
+ // spin openRequest queue further
+ sendNextPendingRequest();
}
}
-QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez()
{
closeServerSocket();
delete cmacCalculator;
@@ -467,7 +474,7 @@ private:
};
-void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &params,
+void QLowEnergyControllerPrivateBluez::startAdvertising(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
const QLowEnergyAdvertisingData &scanResponseData)
{
@@ -476,7 +483,7 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa
advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, *hciManager,
this);
connect(advertiser, &QLeAdvertiser::errorOccurred, this,
- &QLowEnergyControllerPrivate::handleAdvertisingError);
+ &QLowEnergyControllerPrivateBluez::handleAdvertisingError);
}
setState(QLowEnergyController::AdvertisingState);
advertiser->startAdvertising();
@@ -497,16 +504,16 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa
const int socketFd = serverSocket.takeSocket();
serverSocketNotifier = new QSocketNotifier(socketFd, QSocketNotifier::Read, this);
connect(serverSocketNotifier, &QSocketNotifier::activated, this,
- &QLowEnergyControllerPrivate::handleConnectionRequest);
+ &QLowEnergyControllerPrivateBluez::handleConnectionRequest);
}
-void QLowEnergyControllerPrivate::stopAdvertising()
+void QLowEnergyControllerPrivateBluez::stopAdvertising()
{
setState(QLowEnergyController::UnconnectedState);
advertiser->stopAdvertising();
}
-void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
+void QLowEnergyControllerPrivateBluez::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
{
// The spec says that the connection update command can be used by both slave and master
// devices, but BlueZ allows it only for master devices. So for slave devices, we have to use a
@@ -518,7 +525,7 @@ void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnec
hciManager->sendConnectionParameterUpdateRequest(connectionHandle, params);
}
-void QLowEnergyControllerPrivate::connectToDevice()
+void QLowEnergyControllerPrivateBluez::connectToDevice()
{
if (remoteDevice.isNull()) {
qCWarning(QT_BT_BLUEZ) << "Invalid/null remote device address";
@@ -527,8 +534,10 @@ void QLowEnergyControllerPrivate::connectToDevice()
}
setState(QLowEnergyController::ConnectingState);
- if (l2cpSocket)
+ if (l2cpSocket) {
delete l2cpSocket;
+ l2cpSocket = nullptr;
+ }
createServicesForCentralIfRequired();
@@ -550,7 +559,7 @@ void QLowEnergyControllerPrivate::connectToDevice()
if (!device1Manager) {
device1Manager = new RemoteDeviceManager(localAdapter, this);
connect(device1Manager, &RemoteDeviceManager::finished,
- this, &QLowEnergyControllerPrivate::activeConnectionTerminationDone);
+ this, &QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone);
}
QVector<QBluetoothAddress> connectedAddresses;
@@ -568,7 +577,7 @@ void QLowEnergyControllerPrivate::connectToDevice()
/*!
* Handles outcome of attempts to close external connections.
*/
-void QLowEnergyControllerPrivate::activeConnectionTerminationDone()
+void QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone()
{
if (!device1Manager)
return;
@@ -581,6 +590,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone()
qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt";
setError(QLowEnergyController::ConnectionError);
setState(QLowEnergyController::UnconnectedState);
+ l2cpDisconnected();
return;
} else {
establishL2cpClientSocket();
@@ -590,7 +600,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone()
/*!
* Establishes the L2CP client socket.
*/
-void QLowEnergyControllerPrivate::establishL2cpClientSocket()
+void QLowEnergyControllerPrivateBluez::establishL2cpClientSocket()
{
//we are already in Connecting state
@@ -646,7 +656,7 @@ void QLowEnergyControllerPrivate::establishL2cpClientSocket()
loadSigningDataIfNecessary(LocalSigningKey);
}
-void QLowEnergyControllerPrivate::createServicesForCentralIfRequired()
+void QLowEnergyControllerPrivateBluez::createServicesForCentralIfRequired()
{
bool ok = false;
int value = qEnvironmentVariableIntValue("QT_DEFAULT_CENTRAL_SERVICES", &ok);
@@ -712,7 +722,7 @@ void QLowEnergyControllerPrivate::createServicesForCentralIfRequired()
service->setParent(q);
}
-void QLowEnergyControllerPrivate::l2cpConnected()
+void QLowEnergyControllerPrivateBluez::l2cpConnected()
{
Q_Q(QLowEnergyController);
@@ -723,26 +733,37 @@ void QLowEnergyControllerPrivate::l2cpConnected()
emit q->connected();
}
-void QLowEnergyControllerPrivate::disconnectFromDevice()
+void QLowEnergyControllerPrivateBluez::disconnectFromDevice()
{
setState(QLowEnergyController::ClosingState);
- l2cpSocket->close();
+ if (l2cpSocket)
+ l2cpSocket->close();
resetController();
+
+ // this may happen when RemoteDeviceManager::JobType::JobDisconnectDevice
+ // is pending.
+ if (!l2cpSocket) {
+ qWarning(QT_BT_BLUEZ) << "Unexpected closure of device. Cleaning up internal states.";
+ l2cpDisconnected();
+ }
}
-void QLowEnergyControllerPrivate::l2cpDisconnected()
+void QLowEnergyControllerPrivateBluez::l2cpDisconnected()
{
Q_Q(QLowEnergyController);
- if (role == QLowEnergyController::PeripheralRole)
+ if (role == QLowEnergyController::PeripheralRole) {
storeClientConfigurations();
+ remoteDevice.clear();
+ remoteName.clear();
+ }
invalidateServices();
resetController();
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
}
-void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError e)
+void QLowEnergyControllerPrivateBluez::l2cpErrorChanged(QBluetoothSocket::SocketError e)
{
switch (e) {
case QBluetoothSocket::HostNotFoundError:
@@ -775,7 +796,7 @@ void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError
}
-void QLowEnergyControllerPrivate::resetController()
+void QLowEnergyControllerPrivateBluez::resetController()
{
openRequests.clear();
openPrepareWriteRequests.clear();
@@ -784,15 +805,19 @@ void QLowEnergyControllerPrivate::resetController()
requestPending = false;
encryptionChangePending = false;
receivedMtuExchangeRequest = false;
+ mtuSize = ATT_DEFAULT_LE_MTU;
securityLevelValue = -1;
connectionHandle = 0;
- // public API behavior requires stop of advertisement
- if (role == QLowEnergyController::PeripheralRole && advertiser)
- advertiser->stopAdvertising();
+ if (role == QLowEnergyController::PeripheralRole) {
+ // public API behavior requires stop of advertisement
+ if (advertiser)
+ advertiser->stopAdvertising();
+ localAttributes.clear();
+ }
}
-void QLowEnergyControllerPrivate::restartRequestTimer()
+void QLowEnergyControllerPrivateBluez::restartRequestTimer()
{
if (!requestTimer)
return;
@@ -801,7 +826,7 @@ void QLowEnergyControllerPrivate::restartRequestTimer()
requestTimer->start(gattRequestTimeout);
}
-void QLowEnergyControllerPrivate::l2cpReadyRead()
+void QLowEnergyControllerPrivateBluez::l2cpReadyRead()
{
const QByteArray incomingPacket = l2cpSocket->readAll();
qCDebug(QT_BT_BLUEZ) << "Received size:" << incomingPacket.size() << "data:"
@@ -899,7 +924,7 @@ void QLowEnergyControllerPrivate::l2cpReadyRead()
* callback is called. The first pending request in the queue is the request
* that triggered the encryption request.
*/
-void QLowEnergyControllerPrivate::encryptionChangedEvent(
+void QLowEnergyControllerPrivateBluez::encryptionChangedEvent(
const QBluetoothAddress &address, bool wasSuccess)
{
if (!encryptionChangePending) // somebody else caused change event
@@ -948,7 +973,7 @@ void QLowEnergyControllerPrivate::encryptionChangedEvent(
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::sendPacket(const QByteArray &packet)
{
qint64 result = l2cpSocket->write(packet.constData(),
packet.size());
@@ -967,7 +992,7 @@ void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet)
}
-void QLowEnergyControllerPrivate::sendNextPendingRequest()
+void QLowEnergyControllerPrivateBluez::sendNextPendingRequest()
{
if (openRequests.isEmpty() || requestPending || encryptionChangePending)
return;
@@ -1032,7 +1057,7 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery(
return attributeHandle;
}
-void QLowEnergyControllerPrivate::processReply(
+void QLowEnergyControllerPrivateBluez::processReply(
const Request &request, const QByteArray &response)
{
Q_Q(QLowEnergyController);
@@ -1233,9 +1258,9 @@ void QLowEnergyControllerPrivate::processReply(
} else if (!isServiceDiscoveryRun) {
// not encryption problem -> abort readCharacteristic()/readDescriptor() run
if (!descriptorHandle)
- emit service->error(QLowEnergyService::CharacteristicReadError);
+ service->setError(QLowEnergyService::CharacteristicReadError);
else
- emit service->error(QLowEnergyService::DescriptorReadError);
+ service->setError(QLowEnergyService::DescriptorReadError);
}
} else {
if (!descriptorHandle)
@@ -1570,12 +1595,12 @@ void QLowEnergyControllerPrivate::processReply(
}
}
-void QLowEnergyControllerPrivate::discoverServices()
+void QLowEnergyControllerPrivateBluez::discoverServices()
{
sendReadByGroupRequest(0x0001, 0xFFFF, GATT_PRIMARY_SERVICE);
}
-void QLowEnergyControllerPrivate::sendReadByGroupRequest(
+void QLowEnergyControllerPrivateBluez::sendReadByGroupRequest(
QLowEnergyHandle start, QLowEnergyHandle end, quint16 type)
{
//call for primary and secondary services
@@ -1600,7 +1625,7 @@ void QLowEnergyControllerPrivate::sendReadByGroupRequest(
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service)
+void QLowEnergyControllerPrivateBluez::discoverServiceDetails(const QBluetoothUuid &service)
{
if (!serviceList.contains(service)) {
qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString()
@@ -1613,7 +1638,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s
sendReadByTypeRequest(serviceData, serviceData->startHandle, GATT_INCLUDED_SERVICE);
}
-void QLowEnergyControllerPrivate::sendReadByTypeRequest(
+void QLowEnergyControllerPrivateBluez::sendReadByTypeRequest(
QSharedPointer<QLowEnergyServicePrivate> serviceData,
QLowEnergyHandle nextHandle, quint16 attributeType)
{
@@ -1649,7 +1674,7 @@ void QLowEnergyControllerPrivate::sendReadByTypeRequest(
\a readCharacteristics determines whether we intend to read a characteristic;
otherwise we read a descriptor.
*/
-void QLowEnergyControllerPrivate::readServiceValues(
+void QLowEnergyControllerPrivateBluez::readServiceValues(
const QBluetoothUuid &serviceUuid, bool readCharacteristics)
{
quint8 packet[READ_REQUEST_HEADER_SIZE];
@@ -1743,7 +1768,7 @@ void QLowEnergyControllerPrivate::readServiceValues(
open requests to finish the current value read up before
starting the next read request.
*/
-void QLowEnergyControllerPrivate::readServiceValuesByOffset(
+void QLowEnergyControllerPrivateBluez::readServiceValuesByOffset(
uint handleData, quint16 offset, bool isLastValue)
{
const QLowEnergyHandle charHandle = (handleData & 0xffff);
@@ -1782,7 +1807,7 @@ void QLowEnergyControllerPrivate::readServiceValuesByOffset(
openRequests.prepend(request);
}
-void QLowEnergyControllerPrivate::discoverServiceDescriptors(
+void QLowEnergyControllerPrivateBluez::discoverServiceDescriptors(
const QBluetoothUuid &serviceUuid)
{
qCDebug(QT_BT_BLUEZ) << "Discovering descriptor values for"
@@ -1802,7 +1827,7 @@ void QLowEnergyControllerPrivate::discoverServiceDescriptors(
discoverNextDescriptor(service, keys, keys[0]);
}
-void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payload)
+void QLowEnergyControllerPrivateBluez::processUnsolicitedReply(const QByteArray &payload)
{
const char *data = payload.constData();
bool isNotification = (data[0] == ATT_OP_HANDLE_VAL_NOTIFICATION);
@@ -1826,7 +1851,7 @@ void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payl
}
}
-void QLowEnergyControllerPrivate::exchangeMTU()
+void QLowEnergyControllerPrivateBluez::exchangeMTU()
{
qCDebug(QT_BT_BLUEZ) << "Exchanging MTU";
@@ -1845,7 +1870,7 @@ void QLowEnergyControllerPrivate::exchangeMTU()
sendNextPendingRequest();
}
-int QLowEnergyControllerPrivate::securityLevel() const
+int QLowEnergyControllerPrivateBluez::securityLevel() const
{
int socket = l2cpSocket->socketDescriptor();
if (socket < 0) {
@@ -1884,7 +1909,7 @@ int QLowEnergyControllerPrivate::securityLevel() const
return -1;
}
-bool QLowEnergyControllerPrivate::setSecurityLevel(int level)
+bool QLowEnergyControllerPrivateBluez::setSecurityLevel(int level)
{
if (level > BT_SECURITY_HIGH || level < BT_SECURITY_LOW)
return false;
@@ -1931,7 +1956,7 @@ bool QLowEnergyControllerPrivate::setSecurityLevel(int level)
return false;
}
-void QLowEnergyControllerPrivate::discoverNextDescriptor(
+void QLowEnergyControllerPrivateBluez::discoverNextDescriptor(
QSharedPointer<QLowEnergyServicePrivate> serviceData,
const QList<QLowEnergyHandle> pendingCharHandles,
const QLowEnergyHandle startingHandle)
@@ -1968,7 +1993,7 @@ void QLowEnergyControllerPrivate::discoverNextDescriptor(
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest(
+void QLowEnergyControllerPrivateBluez::sendNextPrepareWriteRequest(
const QLowEnergyHandle handle, const QByteArray &newValue,
quint16 offset)
{
@@ -2023,7 +2048,7 @@ void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest(
Otherwise this function sends an execute request for all pending prepare
write requests.
*/
-void QLowEnergyControllerPrivate::sendExecuteWriteRequest(
+void QLowEnergyControllerPrivateBluez::sendExecuteWriteRequest(
const QLowEnergyHandle attrHandle, const QByteArray &newValue,
bool isCancelation)
{
@@ -2055,7 +2080,7 @@ void QLowEnergyControllerPrivate::sendExecuteWriteRequest(
TODO Reliable/prepare write across multiple characteristics is not supported
*/
-void QLowEnergyControllerPrivate::writeCharacteristic(
+void QLowEnergyControllerPrivateBluez::writeCharacteristic(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QByteArray &newValue,
@@ -2073,7 +2098,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(
writeCharacteristicForCentral(service, charHandle, charData.valueHandle, newValue, mode);
}
-void QLowEnergyControllerPrivate::writeDescriptor(
+void QLowEnergyControllerPrivateBluez::writeDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descriptorHandle,
@@ -2092,7 +2117,7 @@ void QLowEnergyControllerPrivate::writeDescriptor(
Reads the value of one specific characteristic.
*/
-void QLowEnergyControllerPrivate::readCharacteristic(
+void QLowEnergyControllerPrivateBluez::readCharacteristic(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle)
{
@@ -2130,7 +2155,7 @@ void QLowEnergyControllerPrivate::readCharacteristic(
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::readDescriptor(
+void QLowEnergyControllerPrivateBluez::readDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descriptorHandle)
@@ -2169,7 +2194,7 @@ void QLowEnergyControllerPrivate::readDescriptor(
* Returns true if the encryption change was successfully requested.
* The request is triggered if we got a related ATT error.
*/
-bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode)
+bool QLowEnergyControllerPrivateBluez::increaseEncryptLevelfRequired(quint8 errorCode)
{
if (securityLevelValue == BT_SECURITY_HIGH)
return false;
@@ -2197,14 +2222,14 @@ bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode
return false;
}
-void QLowEnergyControllerPrivate::handleAdvertisingError()
+void QLowEnergyControllerPrivateBluez::handleAdvertisingError()
{
qCWarning(QT_BT_BLUEZ) << "received advertising error";
setError(QLowEnergyController::AdvertisingError);
setState(QLowEnergyController::UnconnectedState);
}
-bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int minSize,
+bool QLowEnergyControllerPrivateBluez::checkPacketSize(const QByteArray &packet, int minSize,
int maxSize)
{
if (maxSize == -1)
@@ -2217,7 +2242,7 @@ bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int
return false;
}
-bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEnergyHandle handle)
+bool QLowEnergyControllerPrivateBluez::checkHandle(const QByteArray &packet, QLowEnergyHandle handle)
{
if (handle != 0 && handle <= lastLocalHandle)
return true;
@@ -2225,7 +2250,7 @@ bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEner
return false;
}
-bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle,
+bool QLowEnergyControllerPrivateBluez::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle,
QLowEnergyHandle endingHandle)
{
if (startingHandle == 0 || startingHandle > endingHandle) {
@@ -2236,7 +2261,7 @@ bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHand
return true;
}
-void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleExchangeMtuRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.2
@@ -2263,7 +2288,7 @@ void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &pac
qCDebug(QT_BT_BLUEZ) << "Sending server RX MTU" << ATT_MAX_LE_MTU;
}
-void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleFindInformationRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.3.1-2
@@ -2296,7 +2321,7 @@ void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray
}
-void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleFindByTypeValueRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.3.3-4
@@ -2331,7 +2356,7 @@ void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray
sendListResponse(responsePrefix, elemSize, results, elemWriter);
}
-void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleReadByTypeRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.4.1-2
@@ -2384,7 +2409,7 @@ void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &pack
sendListResponse(responsePrefix, elementSize, results, elemWriter);
}
-void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleReadRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.4.3-4
@@ -2411,7 +2436,7 @@ void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet)
sendPacket(response);
}
-void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleReadBlobRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.4.5-6
@@ -2450,7 +2475,7 @@ void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet
sendPacket(response);
}
-void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleReadMultipleRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.4.7-8
@@ -2486,7 +2511,7 @@ void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &pa
sendPacket(response);
}
-void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleReadByGroupTypeRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.4.9-10
@@ -2545,7 +2570,7 @@ void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray
sendListResponse(responsePrefix, elementSize, results, elemWriter);
}
-void QLowEnergyControllerPrivate::updateLocalAttributeValue(
+void QLowEnergyControllerPrivateBluez::updateLocalAttributeValue(
QLowEnergyHandle handle,
const QByteArray &value,
QLowEnergyCharacteristic &characteristic,
@@ -2579,7 +2604,7 @@ void QLowEnergyControllerPrivate::updateLocalAttributeValue(
static bool isNotificationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x1; }
static bool isIndicationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x2; }
-void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral(
+void QLowEnergyControllerPrivateBluez::writeCharacteristicForPeripheral(
QLowEnergyServicePrivate::CharData &charData,
const QByteArray &newValue)
{
@@ -2636,7 +2661,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral(
}
}
-void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service,
+void QLowEnergyControllerPrivateBluez::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service,
QLowEnergyHandle charHandle,
QLowEnergyHandle valueHandle,
const QByteArray &newValue,
@@ -2710,7 +2735,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPoi
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::writeDescriptorForPeripheral(
+void QLowEnergyControllerPrivateBluez::writeDescriptorForPeripheral(
const QSharedPointer<QLowEnergyServicePrivate> &service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descriptorHandle,
@@ -2727,7 +2752,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForPeripheral(
service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue;
}
-void QLowEnergyControllerPrivate::writeDescriptorForCentral(
+void QLowEnergyControllerPrivateBluez::writeDescriptorForCentral(
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descriptorHandle,
const QByteArray &newValue)
@@ -2760,7 +2785,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForCentral(
sendNextPendingRequest();
}
-void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleWriteRequestOrCommand(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.5.1-3
@@ -2854,7 +2879,7 @@ void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray &
}
}
-void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handlePrepareWriteRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.6.1
@@ -2885,7 +2910,7 @@ void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &pa
sendPacket(response);
}
-void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &packet)
+void QLowEnergyControllerPrivateBluez::handleExecuteWriteRequest(const QByteArray &packet)
{
// Spec v4.2, Vol 3, Part F, 3.4.6.3
@@ -2933,7 +2958,7 @@ void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &pa
emit descriptor.d_ptr->descriptorWritten(descriptor, descriptor.value());
}
-void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 handle, quint8 code)
+void QLowEnergyControllerPrivateBluez::sendErrorResponse(quint8 request, quint16 handle, quint8 code)
{
// An ATT command never receives an error response.
if (request == ATT_OP_WRITE_COMMAND || request == ATT_OP_SIGNED_WRITE_COMMAND)
@@ -2949,7 +2974,7 @@ void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 hand
sendPacket(packet);
}
-void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart, int elemSize,
+void QLowEnergyControllerPrivateBluez::sendListResponse(const QByteArray &packetStart, int elemSize,
const QVector<Attribute> &attributes, const ElemWriter &elemWriter)
{
const int offset = packetStart.count();
@@ -2965,19 +2990,19 @@ void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart
sendPacket(response);
}
-void QLowEnergyControllerPrivate::sendNotification(QLowEnergyHandle handle)
+void QLowEnergyControllerPrivateBluez::sendNotification(QLowEnergyHandle handle)
{
sendNotificationOrIndication(ATT_OP_HANDLE_VAL_NOTIFICATION, handle);
}
-void QLowEnergyControllerPrivate::sendIndication(QLowEnergyHandle handle)
+void QLowEnergyControllerPrivateBluez::sendIndication(QLowEnergyHandle handle)
{
Q_ASSERT(!indicationInFlight);
indicationInFlight = true;
sendNotificationOrIndication(ATT_OP_HANDLE_VAL_INDICATION, handle);
}
-void QLowEnergyControllerPrivate::sendNotificationOrIndication(
+void QLowEnergyControllerPrivateBluez::sendNotificationOrIndication(
quint8 opCode,
QLowEnergyHandle handle)
{
@@ -2993,13 +3018,76 @@ void QLowEnergyControllerPrivate::sendNotificationOrIndication(
sendPacket(packet);
}
-void QLowEnergyControllerPrivate::sendNextIndication()
+void QLowEnergyControllerPrivateBluez::sendNextIndication()
{
if (!scheduledIndications.isEmpty())
sendIndication(scheduledIndications.takeFirst());
}
-void QLowEnergyControllerPrivate::handleConnectionRequest()
+static QString nameOfRemoteCentral(const QBluetoothAddress &peerAddress, const QBluetoothAddress &localAdapter)
+{
+ const QString peerAddressString = peerAddress.toString();
+ if (isBluez5()) {
+ OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
+ QStringLiteral("/"),
+ QDBusConnection::systemBus());
+ QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError())
+ return QString();
+
+ ManagedObjectList managedObjectList = reply.value();
+ for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
+ const InterfaceList &ifaceList = it.value();
+
+ for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
+ const QString &iface = jt.key();
+ const QVariantMap &ifaceValues = jt.value();
+
+ if (iface == QStringLiteral("org.bluez.Device1")) {
+ if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddressString)
+ return ifaceValues.value(QStringLiteral("Alias")).toString();
+ }
+ }
+ }
+ return QString();
+ } else {
+ OrgBluezManagerInterface manager(QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus());
+
+ QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(localAdapter.toString());
+ reply.waitForFinished();
+ if (reply.isError())
+ return QString();
+
+ OrgBluezAdapterInterface adapter(QStringLiteral("org.bluez"), reply.value().path(),
+ QDBusConnection::systemBus());
+
+ QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.FindDevice(peerAddressString);
+ deviceObjectPath.waitForFinished();
+ if (deviceObjectPath.isError()) {
+ if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.DoesNotExist"))
+ return QString();
+
+ deviceObjectPath = adapter.CreateDevice(peerAddressString);
+ deviceObjectPath.waitForFinished();
+ if (deviceObjectPath.isError())
+ return QString();
+ }
+
+ OrgBluezDeviceInterface device(QStringLiteral("org.bluez"), deviceObjectPath.value().path(),
+ QDBusConnection::systemBus());
+
+ QDBusPendingReply<QVariantMap> properties = device.GetProperties();
+ properties.waitForFinished();
+ if (properties.isError())
+ return QString();
+
+ return properties.value().value(QStringLiteral("Alias")).toString();
+ }
+}
+
+void QLowEnergyControllerPrivateBluez::handleConnectionRequest()
{
if (state != QLowEnergyController::AdvertisingState) {
qCWarning(QT_BT_BLUEZ) << "Incoming connection request in unexpected state" << state;
@@ -3017,18 +3105,21 @@ void QLowEnergyControllerPrivate::handleConnectionRequest()
serverSocketNotifier->setEnabled(true);
return;
}
+
remoteDevice = QBluetoothAddress(convertAddress(clientAddr.l2_bdaddr.b));
- qCDebug(QT_BT_BLUEZ) << "GATT connection from device" << remoteDevice;
+ remoteName = nameOfRemoteCentral(remoteDevice, localAdapter);
+ qCDebug(QT_BT_BLUEZ) << "GATT connection from device" << remoteDevice << remoteName;
+
if (connectionHandle == 0)
qCWarning(QT_BT_BLUEZ) << "Received client connection, but no connection complete event";
closeServerSocket();
l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this);
connect(l2cpSocket, &QBluetoothSocket::disconnected,
- this, &QLowEnergyControllerPrivate::l2cpDisconnected);
+ this, &QLowEnergyControllerPrivateBluez::l2cpDisconnected);
connect(l2cpSocket, static_cast<void (QBluetoothSocket::*)(QBluetoothSocket::SocketError)>
- (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivate::l2cpErrorChanged);
- connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivate::l2cpReadyRead);
+ (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivateBluez::l2cpErrorChanged);
+ connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivateBluez::l2cpReadyRead);
l2cpSocket->d_ptr->lowEnergySocketType = addressType == QLowEnergyController::PublicAddress
? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM;
l2cpSocket->setSocketDescriptor(clientSocket, QBluetoothServiceInfo::L2capProtocol,
@@ -3041,7 +3132,7 @@ void QLowEnergyControllerPrivate::handleConnectionRequest()
emit q->connected();
}
-void QLowEnergyControllerPrivate::closeServerSocket()
+void QLowEnergyControllerPrivateBluez::closeServerSocket()
{
if (!serverSocketNotifier)
return;
@@ -3051,7 +3142,7 @@ void QLowEnergyControllerPrivate::closeServerSocket()
serverSocketNotifier = nullptr;
}
-bool QLowEnergyControllerPrivate::isBonded() const
+bool QLowEnergyControllerPrivateBluez::isBonded() const
{
// Pairing does not necessarily imply bonding, but we don't know whether the
// bonding flag was set in the original pairing request.
@@ -3059,7 +3150,7 @@ bool QLowEnergyControllerPrivate::isBonded() const
!= QBluetoothLocalDevice::Unpaired;
}
-QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyControllerPrivate::gatherClientConfigData()
+QVector<QLowEnergyControllerPrivateBluez::TempClientConfigurationData> QLowEnergyControllerPrivateBluez::gatherClientConfigData()
{
QVector<TempClientConfigurationData> data;
foreach (const auto &service, localServices) {
@@ -3080,7 +3171,7 @@ QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyCont
return data;
}
-void QLowEnergyControllerPrivate::storeClientConfigurations()
+void QLowEnergyControllerPrivateBluez::storeClientConfigurations()
{
if (!isBonded()) {
clientConfigData.remove(remoteDevice.toUInt64());
@@ -3099,7 +3190,7 @@ void QLowEnergyControllerPrivate::storeClientConfigurations()
clientConfigData.insert(remoteDevice.toUInt64(), clientConfigs);
}
-void QLowEnergyControllerPrivate::restoreClientConfigurations()
+void QLowEnergyControllerPrivateBluez::restoreClientConfigurations()
{
const QVector<TempClientConfigurationData> &tempConfigList = gatherClientConfigData();
const QVector<ClientConfigurationData> &restoredClientConfigs = isBonded()
@@ -3133,7 +3224,7 @@ void QLowEnergyControllerPrivate::restoreClientConfigurations()
sendNextIndication();
}
-void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyType)
+void QLowEnergyControllerPrivateBluez::loadSigningDataIfNecessary(SigningKeyType keyType)
{
const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64());
if (signingDataIt != signingData.constEnd())
@@ -3165,7 +3256,7 @@ void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyT
signingData.insert(remoteDevice.toUInt64(), SigningData(csrk, counter - 1));
}
-void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const
+void QLowEnergyControllerPrivateBluez::storeSignCounter(SigningKeyType keyType) const
{
const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64());
if (signingDataIt == signingData.constEnd())
@@ -3186,12 +3277,12 @@ void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const
settings.setValue(counterKey, counterValue);
}
-QString QLowEnergyControllerPrivate::signingKeySettingsGroup(SigningKeyType keyType) const
+QString QLowEnergyControllerPrivateBluez::signingKeySettingsGroup(SigningKeyType keyType) const
{
return QLatin1String(keyType == LocalSigningKey ? "LocalSignatureKey" : "RemoteSignatureKey");
}
-QString QLowEnergyControllerPrivate::keySettingsFilePath() const
+QString QLowEnergyControllerPrivateBluez::keySettingsFilePath() const
{
return QString::fromLatin1("/var/lib/bluetooth/%1/%2/info")
.arg(localAdapter.toString(), remoteDevice.toString());
@@ -3213,7 +3304,7 @@ static QByteArray uuidToByteArray(const QBluetoothUuid &uuid)
return ba;
}
-void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &service,
+void QLowEnergyControllerPrivateBluez::addToGenericAttributeList(const QLowEnergyServiceData &service,
QLowEnergyHandle startHandle)
{
// Construct generic attribute data for the service with handles as keys.
@@ -3323,7 +3414,7 @@ void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServ
localAttributes[serviceAttribute.handle] = serviceAttribute;
}
-void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &attributes,
+void QLowEnergyControllerPrivateBluez::ensureUniformAttributes(QVector<Attribute> &attributes,
const std::function<int (const Attribute &)> &getSize)
{
if (attributes.isEmpty())
@@ -3336,19 +3427,19 @@ void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &at
}
-void QLowEnergyControllerPrivate::ensureUniformUuidSizes(QVector<Attribute> &attributes)
+void QLowEnergyControllerPrivateBluez::ensureUniformUuidSizes(QVector<Attribute> &attributes)
{
ensureUniformAttributes(attributes,
[](const Attribute &attr) { return getUuidSize(attr.type); });
}
-void QLowEnergyControllerPrivate::ensureUniformValueSizes(QVector<Attribute> &attributes)
+void QLowEnergyControllerPrivateBluez::ensureUniformValueSizes(QVector<Attribute> &attributes)
{
ensureUniformAttributes(attributes,
[](const Attribute &attr) { return attr.value.count(); });
}
-QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::getAttributes(QLowEnergyHandle startHandle,
+QVector<QLowEnergyControllerPrivateBluez::Attribute> QLowEnergyControllerPrivateBluez::getAttributes(QLowEnergyHandle startHandle,
QLowEnergyHandle endHandle, const AttributePredicate &attributePredicate)
{
QVector<Attribute> results;
@@ -3367,7 +3458,7 @@ QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::get
return results;
}
-int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr,
+int QLowEnergyControllerPrivateBluez::checkPermissions(const Attribute &attr,
QLowEnergyCharacteristic::PropertyType type)
{
const bool isReadAccess = type == QLowEnergyCharacteristic::Read;
@@ -3401,12 +3492,12 @@ int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr,
return 0;
}
-int QLowEnergyControllerPrivate::checkReadPermissions(const Attribute &attr)
+int QLowEnergyControllerPrivateBluez::checkReadPermissions(const Attribute &attr)
{
return checkPermissions(attr, QLowEnergyCharacteristic::Read);
}
-int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attributes)
+int QLowEnergyControllerPrivateBluez::checkReadPermissions(QVector<Attribute> &attributes)
{
if (attributes.isEmpty())
return 0;
@@ -3426,7 +3517,7 @@ int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attrib
return 0;
}
-bool QLowEnergyControllerPrivate::verifyMac(const QByteArray &message, const quint128 &csrk,
+bool QLowEnergyControllerPrivateBluez::verifyMac(const QByteArray &message, const quint128 &csrk,
quint32 signCounter, quint64 expectedMac)
{
if (!cmacCalculator)
diff --git a/src/bluetooth/qlowenergycontroller_bluez_p.h b/src/bluetooth/qlowenergycontroller_bluez_p.h
new file mode 100644
index 00000000..66c048be
--- /dev/null
+++ b/src/bluetooth/qlowenergycontroller_bluez_p.h
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QLOWENERGYCONTROLLERBLUEZ_P_H
+#define QLOWENERGYCONTROLLERBLUEZ_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include <QtCore/QQueue>
+#include <QtCore/QVector>
+#include <QtBluetooth/qbluetooth.h>
+#include <QtBluetooth/qlowenergycharacteristic.h>
+#include "qlowenergycontroller.h"
+#include "qlowenergycontrollerbase_p.h"
+
+#include <QtBluetooth/QBluetoothSocket>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyServiceData;
+class QTimer;
+
+class HciManager;
+class LeCmacCalculator;
+class QSocketNotifier;
+class RemoteDeviceManager;
+
+extern void registerQLowEnergyControllerMetaType();
+
+class QLeAdvertiser;
+
+class QLowEnergyControllerPrivateBluez final: public QLowEnergyControllerPrivate
+{
+ Q_OBJECT
+public:
+ QLowEnergyControllerPrivateBluez();
+ ~QLowEnergyControllerPrivateBluez() override;
+
+ void init() override;
+
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &service) override;
+
+ void startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising() override;
+
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
+
+ // read data
+ void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle) override;
+ void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle) override;
+
+ // write data
+ void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QByteArray &newValue, QLowEnergyService::WriteMode mode) override;
+ void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue) override;
+
+ void addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle) override;
+
+ struct Attribute {
+ Attribute() : handle(0) {}
+
+ QLowEnergyHandle handle;
+ QLowEnergyHandle groupEndHandle;
+ QLowEnergyCharacteristic::PropertyTypes properties;
+ QBluetooth::AttAccessConstraints readConstraints;
+ QBluetooth::AttAccessConstraints writeConstraints;
+ QBluetoothUuid type;
+ QByteArray value;
+ int minLength;
+ int maxLength;
+ };
+ QVector<Attribute> localAttributes;
+
+private:
+ quint16 connectionHandle = 0;
+ QBluetoothSocket *l2cpSocket;
+ struct Request {
+ quint8 command;
+ QByteArray payload;
+ // TODO reference below is ugly but until we know all commands and their
+ // requirements this is WIP
+ QVariant reference;
+ QVariant reference2;
+ };
+ QQueue<Request> openRequests;
+
+ struct WriteRequest {
+ WriteRequest() {}
+ WriteRequest(quint16 h, quint16 o, const QByteArray &v)
+ : handle(h), valueOffset(o), value(v) {}
+ quint16 handle;
+ quint16 valueOffset;
+ QByteArray value;
+ };
+ QVector<WriteRequest> openPrepareWriteRequests;
+
+ // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true
+ QVector<QLowEnergyHandle> scheduledIndications;
+ bool indicationInFlight = false;
+
+ struct TempClientConfigurationData {
+ TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr,
+ QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0)
+ : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {}
+
+ QLowEnergyServicePrivate::DescData *descData;
+ QLowEnergyHandle charValueHandle;
+ QLowEnergyHandle configHandle;
+ };
+
+ struct ClientConfigurationData {
+ ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0,
+ quint16 val = 0)
+ : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {}
+
+ QLowEnergyHandle charValueHandle;
+ QLowEnergyHandle configHandle;
+ quint16 configValue;
+ bool charValueWasUpdated = false;
+ };
+ QHash<quint64, QVector<ClientConfigurationData>> clientConfigData;
+
+ struct SigningData {
+ SigningData() = default;
+ SigningData(const quint128 &csrk, quint32 signCounter = quint32(-1))
+ : key(csrk), counter(signCounter) {}
+
+ quint128 key;
+ quint32 counter = quint32(-1);
+ };
+ QHash<quint64, SigningData> signingData;
+ LeCmacCalculator *cmacCalculator = nullptr;
+
+ bool requestPending;
+ quint16 mtuSize;
+ int securityLevelValue;
+ bool encryptionChangePending;
+ bool receivedMtuExchangeRequest = false;
+
+ HciManager *hciManager;
+ QLeAdvertiser *advertiser;
+ QSocketNotifier *serverSocketNotifier;
+ QTimer *requestTimer = nullptr;
+ RemoteDeviceManager* device1Manager = nullptr;
+
+ /*
+ Defines the maximum number of milliseconds the implementation will
+ wait for requests that require a response.
+
+ This addresses the problem that some non-conformant BTLE devices
+ do not implement the request/response system properly. In such cases
+ the queue system would hang forever.
+
+ Once timeout has been triggered we gracefully continue with the next request.
+ Depending on the type of the timed out ATT command we either ignore it
+ or artifically trigger an error response to ensure the API gives the
+ appropriate response. Potentially this can cause problems when the
+ response for the dropped requests arrives very late. That's why a big warning
+ is printed about the compromised state when a timeout is triggered.
+ */
+ int gattRequestTimeout = 20000;
+
+ void handleConnectionRequest();
+ void closeServerSocket();
+
+ bool isBonded() const;
+ QVector<TempClientConfigurationData> gatherClientConfigData();
+ void storeClientConfigurations();
+ void restoreClientConfigurations();
+
+ enum SigningKeyType { LocalSigningKey, RemoteSigningKey };
+ void loadSigningDataIfNecessary(SigningKeyType keyType);
+ void storeSignCounter(SigningKeyType keyType) const;
+ QString signingKeySettingsGroup(SigningKeyType keyType) const;
+ QString keySettingsFilePath() const;
+
+ void sendPacket(const QByteArray &packet);
+ void sendNextPendingRequest();
+ void processReply(const Request &request, const QByteArray &reply);
+
+ void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end,
+ quint16 type);
+ void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData,
+ QLowEnergyHandle nextHandle, quint16 attributeType);
+ void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor);
+ void readServiceValues(const QBluetoothUuid &service,
+ bool readCharacteristics);
+ void readServiceValuesByOffset(uint handleData, quint16 offset,
+ bool isLastValue);
+
+ void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid);
+ void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData,
+ const QList<QLowEnergyHandle> pendingCharHandles,
+ QLowEnergyHandle startingHandle);
+ void processUnsolicitedReply(const QByteArray &msg);
+ void exchangeMTU();
+ bool setSecurityLevel(int level);
+ int securityLevel() const;
+ void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle,
+ const QByteArray &newValue,
+ bool isCancelation);
+ void sendNextPrepareWriteRequest(const QLowEnergyHandle handle,
+ const QByteArray &newValue, quint16 offset);
+ bool increaseEncryptLevelfRequired(quint8 errorCode);
+
+ void resetController();
+
+ void handleAdvertisingError();
+
+ bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1);
+ bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle);
+ bool checkHandlePair(quint8 request, QLowEnergyHandle startingHandle,
+ QLowEnergyHandle endingHandle);
+
+ void handleExchangeMtuRequest(const QByteArray &packet);
+ void handleFindInformationRequest(const QByteArray &packet);
+ void handleFindByTypeValueRequest(const QByteArray &packet);
+ void handleReadByTypeRequest(const QByteArray &packet);
+ void handleReadRequest(const QByteArray &packet);
+ void handleReadBlobRequest(const QByteArray &packet);
+ void handleReadMultipleRequest(const QByteArray &packet);
+ void handleReadByGroupTypeRequest(const QByteArray &packet);
+ void handleWriteRequestOrCommand(const QByteArray &packet);
+ void handlePrepareWriteRequest(const QByteArray &packet);
+ void handleExecuteWriteRequest(const QByteArray &packet);
+
+ void sendErrorResponse(quint8 request, quint16 handle, quint8 code);
+
+ using ElemWriter = std::function<void(const Attribute &, char *&)>;
+ void sendListResponse(const QByteArray &packetStart, int elemSize,
+ const QVector<Attribute> &attributes, const ElemWriter &elemWriter);
+
+ void sendNotification(QLowEnergyHandle handle);
+ void sendIndication(QLowEnergyHandle handle);
+ void sendNotificationOrIndication(quint8 opCode, QLowEnergyHandle handle);
+ void sendNextIndication();
+
+ void ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int(const Attribute &)> &getSize);
+ void ensureUniformUuidSizes(QVector<Attribute> &attributes);
+ void ensureUniformValueSizes(QVector<Attribute> &attributes);
+
+ using AttributePredicate = std::function<bool(const Attribute &)>;
+ QVector<Attribute> getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle,
+ const AttributePredicate &attributePredicate = [](const Attribute &) { return true; });
+
+ int checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type);
+ int checkReadPermissions(const Attribute &attr);
+ int checkReadPermissions(QVector<Attribute> &attributes);
+
+ bool verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter,
+ quint64 expectedMac);
+
+ void updateLocalAttributeValue(
+ QLowEnergyHandle handle,
+ const QByteArray &value,
+ QLowEnergyCharacteristic &characteristic,
+ QLowEnergyDescriptor &descriptor);
+
+ void writeCharacteristicForPeripheral(
+ QLowEnergyServicePrivate::CharData &charData,
+ const QByteArray &newValue);
+ void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service,
+ QLowEnergyHandle charHandle,
+ QLowEnergyHandle valueHandle,
+ const QByteArray &newValue,
+ QLowEnergyService::WriteMode mode);
+
+ void writeDescriptorForPeripheral(
+ const QSharedPointer<QLowEnergyServicePrivate> &service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue);
+ void writeDescriptorForCentral(
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue);
+
+ void restartRequestTimer();
+ void establishL2cpClientSocket();
+ void createServicesForCentralIfRequired();
+
+private slots:
+ void l2cpConnected();
+ void l2cpDisconnected();
+ void l2cpErrorChanged(QBluetoothSocket::SocketError);
+ void l2cpReadyRead();
+ void encryptionChangedEvent(const QBluetoothAddress&, bool);
+ void handleGattRequestTimeout();
+ void activeConnectionTerminationDone();
+};
+
+Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivateBluez::Attribute, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif //QLOWENERGYCONTROLLERBLUEZ_P_H
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
new file mode 100644
index 00000000..16f03405
--- /dev/null
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
@@ -0,0 +1,1090 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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 "qlowenergycontroller_bluezdbus_p.h"
+#include "bluez/adapter1_bluez5_p.h"
+#include "bluez/bluez5_helper_p.h"
+#include "bluez/device1_bluez5_p.h"
+#include "bluez/gattservice1_p.h"
+
+#include "bluez/gattchar1_p.h"
+#include "bluez/gattdesc1_p.h"
+#include "bluez/objectmanager_p.h"
+#include "bluez/properties_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
+
+QLowEnergyControllerPrivateBluezDBus::QLowEnergyControllerPrivateBluezDBus()
+ : QLowEnergyControllerPrivate()
+{
+}
+
+QLowEnergyControllerPrivateBluezDBus::~QLowEnergyControllerPrivateBluezDBus()
+{
+}
+
+void QLowEnergyControllerPrivateBluezDBus::init()
+{
+}
+
+void QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged(
+ const QString &interface, const QVariantMap &changedProperties,
+ const QStringList &/*removedProperties*/)
+{
+ if (interface == QStringLiteral("org.bluez.Device1")) {
+ qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties;
+ if (changedProperties.contains(QStringLiteral("ServicesResolved"))) {
+ //we could check for Connected property as well, but we choose to wait
+ //for ServicesResolved being true
+
+ if (pendingConnect) {
+ bool isResolved = changedProperties.value(QStringLiteral("ServicesResolved")).toBool();
+ if (isResolved) {
+ setState(QLowEnergyController::ConnectedState);
+ pendingConnect = false;
+ disconnectSignalRequired = true;
+ Q_Q(QLowEnergyController);
+ emit q->connected();
+ }
+ }
+ }
+
+ if (changedProperties.contains(QStringLiteral("Connected"))) {
+ bool isConnected = changedProperties.value(QStringLiteral("Connected")).toBool();
+ if (!isConnected) {
+ switch (state) {
+ case QLowEnergyController::ConnectingState:
+ case QLowEnergyController::ConnectedState:
+ case QLowEnergyController::DiscoveringState:
+ case QLowEnergyController::DiscoveredState:
+ case QLowEnergyController::ClosingState:
+ {
+ bool emitDisconnect = disconnectSignalRequired;
+ bool emitError = pendingConnect;
+
+ resetController();
+
+ if (emitError)
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+
+ if (emitDisconnect) {
+ Q_Q(QLowEnergyController);
+ emit q->disconnected();
+ }
+ }
+ break;
+ case QLowEnergyController::AdvertisingState:
+ case QLowEnergyController::UnconnectedState:
+ //ignore
+ break;
+ }
+ }
+ }
+ }
+}
+
+void QLowEnergyControllerPrivateBluezDBus::characteristicPropertiesChanged(
+ QLowEnergyHandle charHandle, const QString &interface,
+ const QVariantMap &changedProperties,
+ const QStringList &/*removedProperties*/)
+{
+ //qCDebug(QT_BT_BLUEZ) << "$$$$$$$$$$$$$$$$$$ char monitor"
+ // << interface << changedProperties << charHandle;
+ if (interface != QStringLiteral("org.bluez.GattCharacteristic1"))
+ return;
+
+ if (!changedProperties.contains(QStringLiteral("Value")))
+ return;
+
+ const QLowEnergyCharacteristic changedChar = characteristicForHandle(charHandle);
+ const QLowEnergyDescriptor ccnDescriptor = changedChar.descriptor(
+ QBluetoothUuid::ClientCharacteristicConfiguration);
+ if (!ccnDescriptor.isValid())
+ return;
+
+ const QByteArray newValue = changedProperties.value(QStringLiteral("Value")).toByteArray();
+ if (changedChar.properties() & QLowEnergyCharacteristic::Read)
+ updateValueOfCharacteristic(charHandle, newValue, false); //TODO upgrade to NEW_VALUE/APPEND_VALUE
+
+ auto service = serviceForHandle(charHandle);
+
+ if (!service.isNull())
+ emit service->characteristicChanged(changedChar, newValue);
+}
+
+void QLowEnergyControllerPrivateBluezDBus::interfacesRemoved(
+ const QDBusObjectPath &objectPath, const QStringList &/*interfaces*/)
+{
+ if (objectPath.path() == device->path()) {
+ resetController();
+ setError(QLowEnergyController::UnknownRemoteDeviceError);
+ qCWarning(QT_BT_BLUEZ) << "DBus Device1 was removed";
+ setState(QLowEnergyController::UnconnectedState);
+ } else if (objectPath.path() == adapter->path()) {
+ resetController();
+ setError(QLowEnergyController::InvalidBluetoothAdapterError);
+ qCWarning(QT_BT_BLUEZ) << "DBus Adapter was removed";
+ setState(QLowEnergyController::UnconnectedState);
+ }
+}
+
+void QLowEnergyControllerPrivateBluezDBus::resetController()
+{
+ if (managerBluez) {
+ delete managerBluez;
+ managerBluez = nullptr;
+ }
+
+ if (adapter) {
+ delete adapter;
+ adapter = nullptr;
+ }
+
+ if (device) {
+ delete device;
+ device = nullptr;
+ }
+
+ if (deviceMonitor) {
+ delete deviceMonitor;
+ deviceMonitor = nullptr;
+ }
+
+ dbusServices.clear();
+ jobs.clear();
+ invalidateServices();
+
+ pendingConnect = pendingDisconnect = disconnectSignalRequired = false;
+ jobPending = false;
+}
+
+void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper()
+{
+ resetController();
+
+ bool ok = false;
+ const QString hostAdapterPath = findAdapterForAddress(localAdapter, &ok);
+ if (!ok || hostAdapterPath.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find suitable bluetooth adapter";
+ setError(QLowEnergyController::InvalidBluetoothAdapterError);
+ return;
+ }
+
+ QScopedPointer<OrgFreedesktopDBusObjectManagerInterface> manager(
+ new OrgFreedesktopDBusObjectManagerInterface(
+ QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus()));
+
+ QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot enumerate Bluetooth devices for GATT connect";
+ setError(QLowEnergyController::ConnectionError);
+ return;
+ }
+
+ QString devicePath;
+ ManagedObjectList managedObjectList = reply.value();
+ for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
+ const InterfaceList &ifaceList = it.value();
+
+ for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
+ const QString &iface = jt.key();
+ const QVariantMap &ifaceValues = jt.value();
+
+ if (iface == QStringLiteral("org.bluez.Device1")) {
+ if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) {
+ devicePath = it.key().path();
+ break;
+ }
+ }
+ }
+
+ if (!devicePath.isEmpty())
+ break;
+ }
+
+ if (devicePath.isEmpty()) {
+ qCDebug(QT_BT_BLUEZ) << "Cannot find targeted remote device. "
+ "Re-running device discovery might help";
+ setError(QLowEnergyController::UnknownRemoteDeviceError);
+ return;
+ }
+
+ managerBluez = manager.take();
+ connect(managerBluez, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
+ this, &QLowEnergyControllerPrivateBluezDBus::interfacesRemoved);
+ adapter = new OrgBluezAdapter1Interface(
+ QStringLiteral("org.bluez"), hostAdapterPath,
+ QDBusConnection::systemBus(), this);
+ device = new OrgBluezDevice1Interface(
+ QStringLiteral("org.bluez"), devicePath,
+ QDBusConnection::systemBus(), this);
+ deviceMonitor = new OrgFreedesktopDBusPropertiesInterface(
+ QStringLiteral("org.bluez"), devicePath,
+ QDBusConnection::systemBus(), this);
+ connect(deviceMonitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
+ this, &QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged);
+}
+
+void QLowEnergyControllerPrivateBluezDBus::connectToDevice()
+{
+ qCDebug(QT_BT_BLUEZ) << "QLowEnergyControllerPrivateBluezDBus::connectToDevice()";
+
+ connectToDeviceHelper();
+
+ if (!adapter || !device)
+ return;
+
+ if (!adapter->powered()) {
+ qCWarning(QT_BT_BLUEZ) << "Error: Local adapter is powered off";
+ setError(QLowEnergyController::ConnectionError);
+ return;
+ }
+
+ setState(QLowEnergyController::ConnectingState);
+
+ //Bluez interface is shared among all platform processes
+ //and hence we might be connected already
+ if (device->connected() && device->servicesResolved()) {
+ //connectToDevice is noop
+ disconnectSignalRequired = true;
+
+ setState(QLowEnergyController::ConnectedState);
+ Q_Q(QLowEnergyController);
+ emit q->connected();
+ return;
+ }
+
+ pendingConnect = true;
+
+ QDBusPendingReply<> reply = device->Connect();
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this,
+ [=](QDBusPendingCallWatcher* call) {
+ QDBusPendingReply<> reply = *call;
+ if (reply.isError()) {
+ qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::connect() failed"
+ << reply.reply().errorName()
+ << reply.reply().errorMessage();
+ bool emitDisconnect = disconnectSignalRequired;
+ resetController();
+ setError(QLowEnergyController::UnknownError);
+ setState(QLowEnergyController::UnconnectedState);
+ if (emitDisconnect) {
+ Q_Q(QLowEnergyController);
+ emit q->disconnected();
+ }
+ } // else -> connected when Connected property is set to true (see devicePropertiesChanged())
+ call->deleteLater();
+ });
+}
+
+void QLowEnergyControllerPrivateBluezDBus::disconnectFromDevice()
+{
+ setState(QLowEnergyController::ClosingState);
+
+ pendingDisconnect = true;
+
+ QDBusPendingReply<> reply = device->Disconnect();
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this,
+ [=](QDBusPendingCallWatcher* call) {
+ QDBusPendingReply<> reply = *call;
+ if (reply.isError()) {
+ qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::disconnect() failed"
+ << reply.reply().errorName()
+ << reply.reply().errorMessage();
+ bool emitDisconnect = disconnectSignalRequired;
+ resetController();
+ setState(QLowEnergyController::UnconnectedState);
+ if (emitDisconnect) {
+ Q_Q(QLowEnergyController);
+ emit q->disconnected();
+ }
+ }
+ call->deleteLater();
+ });
+}
+
+void QLowEnergyControllerPrivateBluezDBus::discoverServices()
+{
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot discover services";
+ setError(QLowEnergyController::UnknownError);
+ setState(QLowEnergyController::DiscoveredState);
+ return;
+ }
+
+ Q_Q(QLowEnergyController);
+
+ const ManagedObjectList managedObjectList = reply.value();
+ const QString servicePathPrefix = device->path().append(QStringLiteral("/service"));
+ for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
+ const InterfaceList &ifaceList = it.value();
+ if (!it.key().path().startsWith(servicePathPrefix))
+ continue;
+
+ for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
+ const QString &iface = jt.key();
+
+ if (iface == QStringLiteral("org.bluez.GattService1")) {
+ QScopedPointer<OrgBluezGattService1Interface> service(new OrgBluezGattService1Interface(
+ QStringLiteral("org.bluez"),it.key().path(),
+ QDBusConnection::systemBus(), this));
+
+ QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create();
+ priv->uuid = QBluetoothUuid(service->uUID());
+ service->primary()
+ ? priv->type = QLowEnergyService::PrimaryService
+ : priv->type = QLowEnergyService::IncludedService;
+ priv->setController(this);
+
+ GattService serviceContainer;
+ serviceContainer.servicePath = it.key().path();
+
+ serviceList.insert(priv->uuid, priv);
+ dbusServices.insert(priv->uuid, serviceContainer);
+
+ emit q->serviceDiscovered(priv->uuid);
+ }
+ }
+ }
+
+ setState(QLowEnergyController::DiscoveredState);
+ emit q->discoveryFinished();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::discoverServiceDetails(const QBluetoothUuid &service)
+{
+ if (!serviceList.contains(service) || !dbusServices.contains(service)) {
+ qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString()
+ << "not possible";
+ return;
+ }
+
+ //clear existing service data and run new discovery
+ QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(service);
+ serviceData->characteristicList.clear();
+
+ GattService &dbusData = dbusServices[service];
+ dbusData.characteristics.clear();
+
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot discover services";
+ setError(QLowEnergyController::UnknownError);
+ setState(QLowEnergyController::DiscoveredState);
+ return;
+ }
+
+ QStringList descriptorPaths;
+ const ManagedObjectList managedObjectList = reply.value();
+ for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
+ const InterfaceList &ifaceList = it.value();
+ if (!it.key().path().startsWith(dbusData.servicePath))
+ continue;
+
+ for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
+ const QString &iface = jt.key();
+ if (iface == QStringLiteral("org.bluez.GattCharacteristic1")) {
+ auto charInterface = QSharedPointer<OrgBluezGattCharacteristic1Interface>::create(
+ QStringLiteral("org.bluez"), it.key().path(),
+ QDBusConnection::systemBus());
+ GattCharacteristic dbusCharData;
+ dbusCharData.characteristic = charInterface;
+ dbusData.characteristics.append(dbusCharData);
+ } else if (iface == QStringLiteral("org.bluez.GattDescriptor1")) {
+ auto descInterface = QSharedPointer<OrgBluezGattDescriptor1Interface>::create(
+ QStringLiteral("org.bluez"), it.key().path(),
+ QDBusConnection::systemBus());
+ bool found = false;
+ for (GattCharacteristic &dbusCharData : dbusData.characteristics) {
+ if (!descInterface->path().startsWith(
+ dbusCharData.characteristic->path()))
+ continue;
+
+ found = true;
+ dbusCharData.descriptors.append(descInterface);
+ break;
+ }
+
+ Q_ASSERT(found);
+ if (!found)
+ qCWarning(QT_BT_BLUEZ) << "Descriptor discovery error";
+ }
+ }
+ }
+
+ //populate servicePrivate based on dbus data
+ serviceData->startHandle = runningHandle++;
+ for (GattCharacteristic &dbusChar : dbusData.characteristics) {
+ const QLowEnergyHandle indexHandle = runningHandle++;
+ QLowEnergyServicePrivate::CharData charData;
+
+ // characteristic data
+ charData.valueHandle = runningHandle++;
+ const QStringList properties = dbusChar.characteristic->flags();
+
+ for (const auto &entry : properties) {
+ if (entry == QStringLiteral("broadcast"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::Broadcasting, true);
+ else if (entry == QStringLiteral("read"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::Read, true);
+ else if (entry == QStringLiteral("write-without-response"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::WriteNoResponse, true);
+ else if (entry == QStringLiteral("write"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::Write, true);
+ else if (entry == QStringLiteral("notify"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::Notify, true);
+ else if (entry == QStringLiteral("indicate"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::Indicate, true);
+ else if (entry == QStringLiteral("authenticated-signed-writes"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::WriteSigned, true);
+ else if (entry == QStringLiteral("reliable-write"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true);
+ else if (entry == QStringLiteral("writable-auxiliaries"))
+ charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true);
+ //all others ignored - not relevant for this API
+ }
+
+ charData.uuid = QBluetoothUuid(dbusChar.characteristic->uUID());
+
+ // schedule read for initial char value
+ if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) {
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::CharRead, GattJob::ServiceDiscovery});
+ job.service = serviceData;
+ job.handle = indexHandle;
+ jobs.append(job);
+ }
+
+ // descriptor data
+ for (const auto &descEntry : qAsConst(dbusChar.descriptors)) {
+ const QLowEnergyHandle descriptorHandle = runningHandle++;
+ QLowEnergyServicePrivate::DescData descData;
+ descData.uuid = QBluetoothUuid(descEntry->uUID());
+ charData.descriptorList.insert(descriptorHandle, descData);
+
+
+ // every ClientCharacteristicConfiguration needs to track property changes
+ if (descData.uuid
+ == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
+ dbusChar.charMonitor = QSharedPointer<OrgFreedesktopDBusPropertiesInterface>::create(
+ QStringLiteral("org.bluez"),
+ dbusChar.characteristic->path(),
+ QDBusConnection::systemBus(), this);
+ connect(dbusChar.charMonitor.data(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
+ this, [this, indexHandle](const QString &interface, const QVariantMap &changedProperties,
+ const QStringList &removedProperties) {
+
+ characteristicPropertiesChanged(indexHandle, interface,
+ changedProperties, removedProperties);
+ });
+ }
+
+ // schedule read for initial descriptor value
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::DescRead, GattJob::ServiceDiscovery});
+ job.service = serviceData;
+ job.handle = descriptorHandle;
+ jobs.append(job);
+ }
+
+ serviceData->characteristicList[indexHandle] = charData;
+ }
+
+ serviceData->endHandle = runningHandle++;
+
+ // last job is last step of service discovery
+ if (!jobs.isEmpty()) {
+ GattJob &lastJob = jobs.last();
+ lastJob.flags.setFlag(GattJob::LastServiceDiscovery, true);
+ } else {
+ serviceData->setState(QLowEnergyService::ServiceDiscovered);
+ }
+
+ scheduleNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::prepareNextJob()
+{
+ jobs.takeFirst(); // finish last job
+ jobPending = false;
+
+ scheduleNextJob(); // continue with next job - if available
+}
+
+void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWatcher *call)
+{
+ if (!jobPending || jobs.isEmpty()) {
+ // this may happen when service disconnects before dbus watcher returns later on
+ qCWarning(QT_BT_BLUEZ) << "Aborting onCharReadFinished due to disconnect";
+ Q_ASSERT(state == QLowEnergyController::UnconnectedState);
+ return;
+ }
+
+ const GattJob nextJob = jobs.constFirst();
+ Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead));
+
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
+ if (service.isNull() || !dbusServices.contains(service->uuid)) {
+ qCWarning(QT_BT_BLUEZ) << "onCharReadFinished: Invalid GATT job. Skipping.";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(nextJob.handle);
+
+ bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
+ QDBusPendingReply<QByteArray> reply = *call;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot initiate reading of" << charData.uuid
+ << "of service" << service->uuid
+ << reply.error().name() << reply.error().message();
+ if (!isServiceDiscovery)
+ service->setError(QLowEnergyService::CharacteristicReadError);
+ } else {
+ qCDebug(QT_BT_BLUEZ) << "Read Char:" << charData.uuid << reply.value().toHex();
+ if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
+ updateValueOfCharacteristic(nextJob.handle, reply.value(), false);
+
+ if (isServiceDiscovery) {
+ if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
+ service->setState(QLowEnergyService::ServiceDiscovered);
+ } else {
+ QLowEnergyCharacteristic ch(service, nextJob.handle);
+ emit service->characteristicRead(ch, reply.value());
+ }
+ }
+
+ call->deleteLater();
+ prepareNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWatcher *call)
+{
+ if (!jobPending || jobs.isEmpty()) {
+ // this may happen when service disconnects before dbus watcher returns later on
+ qCWarning(QT_BT_BLUEZ) << "Aborting onDescReadFinished due to disconnect";
+ Q_ASSERT(state == QLowEnergyController::UnconnectedState);
+ return;
+ }
+
+ const GattJob nextJob = jobs.constFirst();
+ Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead));
+
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
+ if (service.isNull() || !dbusServices.contains(service->uuid)) {
+ qCWarning(QT_BT_BLUEZ) << "onDescReadFinished: Invalid GATT job. Skipping.";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
+ if (!ch.isValid()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find char for desc read (onDescReadFinished 1).";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(ch.attributeHandle());
+
+ if (!charData.descriptorList.contains(nextJob.handle)) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor (onDescReadFinished 2).";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
+ const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
+
+ QDBusPendingReply<QByteArray> reply = *call;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot read descriptor (onDescReadFinished 3): "
+ << charData.descriptorList[nextJob.handle].uuid
+ << charData.uuid
+ << reply.error().name() << reply.error().message();
+ if (!isServiceDiscovery)
+ service->setError(QLowEnergyService::DescriptorReadError);
+ } else {
+ qCDebug(QT_BT_BLUEZ) << "Read Desc:" << reply.value();
+ updateValueOfDescriptor(ch.attributeHandle(), nextJob.handle, reply.value(), false);
+
+ if (isServiceDiscovery) {
+ if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
+ service->setState(QLowEnergyService::ServiceDiscovered);
+ } else {
+ QLowEnergyDescriptor desc(service, ch.attributeHandle(), nextJob.handle);
+ emit service->descriptorRead(desc, reply.value());
+ }
+ }
+
+ call->deleteLater();
+ prepareNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallWatcher *call)
+{
+ if (!jobPending || jobs.isEmpty()) {
+ // this may happen when service disconnects before dbus watcher returns later on
+ qCWarning(QT_BT_BLUEZ) << "Aborting onCharWriteFinished due to disconnect";
+ Q_ASSERT(state == QLowEnergyController::UnconnectedState);
+ return;
+ }
+
+ const GattJob nextJob = jobs.constFirst();
+ Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite));
+
+ QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
+ if (!dbusServices.contains(service->uuid)) {
+ qCWarning(QT_BT_BLUEZ) << "onCharWriteFinished: Invalid GATT job. Skipping.";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(nextJob.handle);
+
+ QDBusPendingReply<> reply = *call;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << charData.uuid
+ << "of service" << service->uuid
+ << reply.error().name() << reply.error().message();
+ service->setError(QLowEnergyService::CharacteristicWriteError);
+ } else {
+ if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
+ updateValueOfCharacteristic(nextJob.handle, nextJob.value, false);
+
+ QLowEnergyCharacteristic ch(service, nextJob.handle);
+ // write without respone implies zero feedback
+ if (nextJob.writeMode == QLowEnergyService::WriteWithResponse) {
+ qCDebug(QT_BT_BLUEZ) << "Written Char:" << charData.uuid << nextJob.value.toHex();
+ emit service->characteristicWritten(ch, nextJob.value);
+ }
+ }
+
+ call->deleteLater();
+ prepareNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished(QDBusPendingCallWatcher *call)
+{
+ if (!jobPending || jobs.isEmpty()) {
+ // this may happen when service disconnects before dbus watcher returns later on
+ qCWarning(QT_BT_BLUEZ) << "Aborting onDescWriteFinished due to disconnect";
+ Q_ASSERT(state == QLowEnergyController::UnconnectedState);
+ return;
+ }
+
+ const GattJob nextJob = jobs.constFirst();
+ Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite));
+
+ QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
+ if (!dbusServices.contains(service->uuid)) {
+ qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Invalid GATT job. Skipping.";
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyCharacteristic associatedChar = characteristicForHandle(nextJob.handle);
+ const QLowEnergyDescriptor descriptor = descriptorForHandle(nextJob.handle);
+ if (!associatedChar.isValid() || !descriptor.isValid()) {
+ qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Cannot find associated char/desc: "
+ << associatedChar.isValid();
+ call->deleteLater();
+ prepareNextJob();
+ return;
+ }
+
+ QDBusPendingReply<> reply = *call;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << descriptor.uuid()
+ << "of char" << associatedChar.uuid()
+ << "of service" << service->uuid
+ << reply.error().name() << reply.error().message();
+ service->setError(QLowEnergyService::DescriptorWriteError);
+ } else {
+ qCDebug(QT_BT_BLUEZ) << "Write Desc:" << descriptor.uuid() << nextJob.value.toHex();
+ updateValueOfDescriptor(associatedChar.attributeHandle(), nextJob.handle,
+ nextJob.value, false);
+ emit service->descriptorWritten(descriptor, nextJob.value);
+ }
+
+ call->deleteLater();
+ prepareNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::scheduleNextJob()
+{
+ if (jobPending || jobs.isEmpty())
+ return;
+
+ jobPending = true;
+
+ const GattJob nextJob = jobs.constFirst();
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
+ if (service.isNull() || !dbusServices.contains(service->uuid)) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadChar). Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const GattService &dbusServiceData = dbusServices[service->uuid];
+
+ if (nextJob.flags.testFlag(GattJob::CharRead)) {
+ // characteristic reading ***************************************
+ if (!service->characteristicList.contains(nextJob.handle)) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when reading. Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(nextJob.handle);
+ bool foundChar = false;
+ for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
+ if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
+ continue;
+
+ QDBusPendingReply<QByteArray> reply = gattChar.characteristic->ReadValue(QVariantMap());
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, &QLowEnergyControllerPrivateBluezDBus::onCharReadFinished);
+
+ foundChar = true;
+ break;
+ }
+
+ if (!foundChar) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find char for reading. Skipping.";
+ prepareNextJob();
+ return;
+ }
+ } else if (nextJob.flags.testFlag(GattJob::CharWrite)) {
+ // characteristic writing ***************************************
+ if (!service->characteristicList.contains(nextJob.handle)) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when writing. Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(nextJob.handle);
+ bool foundChar = false;
+ for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
+ if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
+ continue;
+
+ QDBusPendingReply<> reply = gattChar.characteristic->WriteValue(nextJob.value, QVariantMap());
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, &QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished);
+
+ foundChar = true;
+ break;
+ }
+
+ if (!foundChar) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find char for writing. Skipping.";
+ prepareNextJob();
+ return;
+ }
+ } else if (nextJob.flags.testFlag(GattJob::DescRead)) {
+ // descriptor reading ***************************************
+ QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
+ if (!ch.isValid()) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 1). Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(ch.attributeHandle());
+ if (!charData.descriptorList.contains(nextJob.handle)) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 2). Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
+ bool foundDesc = false;
+ for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
+ if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
+ continue;
+
+ for (const auto &gattDesc : qAsConst(gattChar.descriptors)) {
+ if (descUuid != QBluetoothUuid(gattDesc->uUID()))
+ continue;
+
+ QDBusPendingReply<QByteArray> reply = gattDesc->ReadValue(QVariantMap());
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, &QLowEnergyControllerPrivateBluezDBus::onDescReadFinished);
+ foundDesc = true;
+ break;
+ }
+
+ if (foundDesc)
+ break;
+ }
+
+ if (!foundDesc) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for reading. Skipping.";
+ prepareNextJob();
+ return;
+ }
+ } else if (nextJob.flags.testFlag(GattJob::DescWrite)) {
+ // descriptor writing ***************************************
+ const QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
+ if (!ch.isValid()) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 1). Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charData =
+ service->characteristicList.value(ch.attributeHandle());
+ if (!charData.descriptorList.contains(nextJob.handle)) {
+ qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 2). Skipping.";
+ prepareNextJob();
+ return;
+ }
+
+ const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
+ bool foundDesc = false;
+ for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
+ if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
+ continue;
+
+ for (const auto &gattDesc : qAsConst(gattChar.descriptors)) {
+ if (descUuid != QBluetoothUuid(gattDesc->uUID()))
+ continue;
+
+ //notifications enabled via characteristics Start/StopNotify() functions
+ //otherwise regular WriteValue() calls on descriptor interface
+ if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
+ const QByteArray value = nextJob.value;
+
+ QDBusPendingReply<> reply;
+ qCDebug(QT_BT_BLUEZ) << "Init CCC change to" << value.toHex()
+ << charData.uuid << service->uuid;
+ if (value == QByteArray::fromHex("0100") || value == QByteArray::fromHex("0200"))
+ reply = gattChar.characteristic->StartNotify();
+ else
+ reply = gattChar.characteristic->StopNotify();
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);
+ } else {
+ QDBusPendingReply<> reply = gattDesc->WriteValue(nextJob.value, QVariantMap());
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);
+
+ }
+
+ foundDesc = true;
+ break;
+ }
+
+ if (foundDesc)
+ break;
+ }
+
+ if (!foundDesc) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for writing. Skipping.";
+ prepareNextJob();
+ return;
+ }
+ } else {
+ qCWarning(QT_BT_BLUEZ) << "Unknown gatt job type. Skipping.";
+ prepareNextJob();
+ }
+}
+
+void QLowEnergyControllerPrivateBluezDBus::readCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle)
+{
+ Q_ASSERT(!service.isNull());
+ if (!service->characteristicList.contains(charHandle)) {
+ qCWarning(QT_BT_BLUEZ) << "Read characteristic does not belong to service"
+ << service->uuid;
+ return;
+ }
+
+ const QLowEnergyServicePrivate::CharData &charDetails
+ = service->characteristicList[charHandle];
+ if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) {
+ // if this succeeds the device has a bug, char is advertised as
+ // non-readable. We try to be permissive and let the remote
+ // device answer to the read attempt
+ qCWarning(QT_BT_BLUEZ) << "Reading non-readable char" << charHandle;
+ }
+
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::CharRead});
+ job.service = service;
+ job.handle = charHandle;
+ jobs.append(job);
+
+ scheduleNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::readDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle)
+{
+ Q_ASSERT(!service.isNull());
+ if (!service->characteristicList.contains(charHandle))
+ return;
+
+ const QLowEnergyServicePrivate::CharData &charDetails
+ = service->characteristicList[charHandle];
+ if (!charDetails.descriptorList.contains(descriptorHandle))
+ return;
+
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::DescRead});
+ job.service = service;
+ job.handle = descriptorHandle;
+ jobs.append(job);
+
+ scheduleNextJob();
+}
+
+void QLowEnergyControllerPrivateBluezDBus::writeCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QByteArray &newValue,
+ QLowEnergyService::WriteMode writeMode)
+{
+ Q_ASSERT(!service.isNull());
+ if (!service->characteristicList.contains(charHandle)) {
+ qCWarning(QT_BT_BLUEZ) << "Write characteristic does not belong to service"
+ << service->uuid;
+ return;
+ }
+
+ if (role == QLowEnergyController::CentralRole) {
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::CharWrite});
+ job.service = service;
+ job.handle = charHandle;
+ job.value = newValue;
+ job.writeMode = writeMode;
+ jobs.append(job);
+
+ scheduleNextJob();
+ } else {
+ qWarning(QT_BT_BLUEZ) << "writeCharacteristic() not implemented for DBus Bluez GATT";
+ service->setError(QLowEnergyService::CharacteristicWriteError);
+ }
+}
+
+void QLowEnergyControllerPrivateBluezDBus::writeDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue)
+{
+ Q_ASSERT(!service.isNull());
+ if (!service->characteristicList.contains(charHandle))
+ return;
+
+ if (role == QLowEnergyController::CentralRole) {
+ GattJob job;
+ job.flags = GattJob::JobFlags({GattJob::DescWrite});
+ job.service = service;
+ job.handle = descriptorHandle;
+ job.value = newValue;
+ jobs.append(job);
+
+ scheduleNextJob();
+ } else {
+ qWarning(QT_BT_BLUEZ) << "writeDescriptor() peripheral not implemented for DBus Bluez GATT";
+ service->setError(QLowEnergyService::CharacteristicWriteError);
+ }
+}
+
+void QLowEnergyControllerPrivateBluezDBus::startAdvertising(
+ const QLowEnergyAdvertisingParameters &/* params */,
+ const QLowEnergyAdvertisingData &/* advertisingData */,
+ const QLowEnergyAdvertisingData &/* scanResponseData */)
+{
+}
+
+void QLowEnergyControllerPrivateBluezDBus::stopAdvertising()
+{
+}
+
+void QLowEnergyControllerPrivateBluezDBus::requestConnectionUpdate(
+ const QLowEnergyConnectionParameters & /* params */)
+{
+}
+
+void QLowEnergyControllerPrivateBluezDBus::addToGenericAttributeList(
+ const QLowEnergyServiceData &/* service */,
+ QLowEnergyHandle /* startHandle */)
+{
+}
+
+QLowEnergyService *QLowEnergyControllerPrivateBluezDBus::addServiceHelper(
+ const QLowEnergyServiceData &/*service*/)
+{
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus_p.h b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h
new file mode 100644
index 00000000..0e0bfcb5
--- /dev/null
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QLOWENERGYCONTROLLERPRIVATEDBUS_P_H
+#define QLOWENERGYCONTROLLERPRIVATEDBUS_P_H
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qlowenergycontroller.h"
+#include "qlowenergycontrollerbase_p.h"
+
+#include <QtDBus/QDBusObjectPath>
+
+class OrgBluezAdapter1Interface;
+class OrgBluezDevice1Interface;
+class OrgBluezGattCharacteristic1Interface;
+class OrgBluezGattDescriptor1Interface;
+class OrgBluezGattService1Interface;
+class OrgFreedesktopDBusObjectManagerInterface;
+class OrgFreedesktopDBusPropertiesInterface;
+
+QT_BEGIN_NAMESPACE
+
+class QDBusPendingCallWatcher;
+
+class QLowEnergyControllerPrivateBluezDBus final : public QLowEnergyControllerPrivate
+{
+ Q_OBJECT
+public:
+ QLowEnergyControllerPrivateBluezDBus();
+ ~QLowEnergyControllerPrivateBluezDBus() override;
+
+ void init() override;
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &/*service*/) override;
+
+ void readCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/) override;
+ void readDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QLowEnergyHandle /*descriptorHandle*/) override;
+
+ void writeCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QByteArray &/*newValue*/,
+ QLowEnergyService::WriteMode /*writeMode*/) override;
+ void writeDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QLowEnergyHandle /*descriptorHandle*/,
+ const QByteArray &/*newValue*/) override;
+
+ void startAdvertising(
+ const QLowEnergyAdvertisingParameters &/* params */,
+ const QLowEnergyAdvertisingData &/* advertisingData */,
+ const QLowEnergyAdvertisingData &/* scanResponseData */) override;
+ void stopAdvertising() override;
+
+ void requestConnectionUpdate(
+ const QLowEnergyConnectionParameters & /* params */) override;
+ void addToGenericAttributeList(
+ const QLowEnergyServiceData &/* service */,
+ QLowEnergyHandle /* startHandle */) override;
+
+ QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service) override;
+
+
+private:
+ void connectToDeviceHelper();
+ void resetController();
+
+ void scheduleNextJob();
+
+private slots:
+ void devicePropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
+ const QStringList &/*invalidatedProperties*/);
+ void characteristicPropertiesChanged(QLowEnergyHandle charHandle, const QString &interface,
+ const QVariantMap &changedProperties,
+ const QStringList &invalidatedProperties);
+ void interfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces);
+
+ void onCharReadFinished(QDBusPendingCallWatcher *call);
+ void onDescReadFinished(QDBusPendingCallWatcher *call);
+ void onCharWriteFinished(QDBusPendingCallWatcher *call);
+ void onDescWriteFinished(QDBusPendingCallWatcher *call);
+private:
+ OrgBluezAdapter1Interface* adapter{};
+ OrgBluezDevice1Interface* device{};
+ OrgFreedesktopDBusObjectManagerInterface* managerBluez{};
+ OrgFreedesktopDBusPropertiesInterface* deviceMonitor{};
+
+ bool pendingConnect = false;
+ bool pendingDisconnect = false;
+ bool disconnectSignalRequired = false;
+
+ struct GattCharacteristic
+ {
+ QSharedPointer<OrgBluezGattCharacteristic1Interface> characteristic;
+ QSharedPointer<OrgFreedesktopDBusPropertiesInterface> charMonitor;
+ QVector<QSharedPointer<OrgBluezGattDescriptor1Interface>> descriptors;
+ };
+
+ struct GattService
+ {
+ QString servicePath;
+ QVector<GattCharacteristic> characteristics;
+ };
+
+ QHash<QBluetoothUuid, GattService> dbusServices;
+ QLowEnergyHandle runningHandle = 1;
+
+ struct GattJob {
+ enum JobFlag {
+ Unset = 0x00,
+ CharRead = 0x01,
+ CharWrite = 0x02,
+ DescRead = 0x04,
+ DescWrite = 0x08,
+ ServiceDiscovery = 0x10,
+ LastServiceDiscovery = 0x20
+ };
+ Q_DECLARE_FLAGS(JobFlags, JobFlag)
+
+ JobFlags flags = GattJob::Unset;
+ QLowEnergyHandle handle;
+ QByteArray value;
+ QLowEnergyService::WriteMode writeMode = QLowEnergyService::WriteWithResponse;
+ QSharedPointer<QLowEnergyServicePrivate> service;
+ };
+
+ QVector<GattJob> jobs;
+ bool jobPending = false;
+
+ void prepareNextJob();
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOWENERGYCONTROLLERPRIVATEDBUS_P_H
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm
index 1206ef42..2958e6ed 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_osx.mm
@@ -72,6 +72,8 @@ static void registerQLowEnergyControllerMetaType()
qRegisterMetaType<QLowEnergyController::Error>();
qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle");
qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate> >();
+ qRegisterMetaType<QLowEnergyCharacteristic>();
+ qRegisterMetaType<QLowEnergyDescriptor>();
initDone = true;
}
}
diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_osx_p.h
index 5cceb9e6..24b7c6e9 100644
--- a/src/bluetooth/qlowenergycontroller_osx_p.h
+++ b/src/bluetooth/qlowenergycontroller_osx_p.h
@@ -54,7 +54,7 @@
#include "osx/osxbtperipheralmanager_p.h"
#include "qlowenergyserviceprivate_p.h"
#include "osx/osxbtcentralmanager_p.h"
-#include "qlowenergycontroller_p.h"
+#include "qlowenergycontrollerbase_p.h"
#include "qlowenergycontroller.h"
#include "osx/osxbtnotifier_p.h"
#include "osx/osxbtutility_p.h"
diff --git a/src/bluetooth/qlowenergycontroller_p.cpp b/src/bluetooth/qlowenergycontroller_p.cpp
index 27d16093..c3605f05 100644
--- a/src/bluetooth/qlowenergycontroller_p.cpp
+++ b/src/bluetooth/qlowenergycontroller_p.cpp
@@ -38,33 +38,26 @@
****************************************************************************/
#include "qlowenergycontroller_p.h"
-#ifndef QT_IOS_BLUETOOTH
#include "dummy/dummy_helper_p.h"
-#endif
QT_BEGIN_NAMESPACE
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
- : QObject(),
- state(QLowEnergyController::UnconnectedState),
- error(QLowEnergyController::NoError),
- lastLocalHandle(0)
+QLowEnergyControllerPrivateCommon::QLowEnergyControllerPrivateCommon()
+ : QLowEnergyControllerPrivate()
{
-#ifndef QT_IOS_BLUETOOTH
printDummyWarning();
-#endif
registerQLowEnergyControllerMetaType();
}
-QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivateCommon::~QLowEnergyControllerPrivateCommon()
{
}
-void QLowEnergyControllerPrivate::init()
+void QLowEnergyControllerPrivateCommon::init()
{
}
-void QLowEnergyControllerPrivate::connectToDevice()
+void QLowEnergyControllerPrivateCommon::connectToDevice()
{
// required to pass unit test on default backend
if (remoteDevice.isNull()) {
@@ -73,39 +66,39 @@ void QLowEnergyControllerPrivate::connectToDevice()
return;
}
- qWarning() << "QLowEnergyControllerPrivate::connectToDevice(): Not implemented";
+ qWarning() << "QLowEnergyControllerPrivateCommon::connectToDevice(): Not implemented";
setError(QLowEnergyController::UnknownError);
}
-void QLowEnergyControllerPrivate::disconnectFromDevice()
+void QLowEnergyControllerPrivateCommon::disconnectFromDevice()
{
}
-void QLowEnergyControllerPrivate::discoverServices()
+void QLowEnergyControllerPrivateCommon::discoverServices()
{
}
-void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &/*service*/)
+void QLowEnergyControllerPrivateCommon::discoverServiceDetails(const QBluetoothUuid &/*service*/)
{
}
-void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+void QLowEnergyControllerPrivateCommon::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
const QLowEnergyHandle /*charHandle*/)
{
}
-void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+void QLowEnergyControllerPrivateCommon::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
const QLowEnergyHandle /*charHandle*/,
const QLowEnergyHandle /*descriptorHandle*/)
{
}
-void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+void QLowEnergyControllerPrivateCommon::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
const QLowEnergyHandle /*charHandle*/,
const QByteArray &/*newValue*/,
QLowEnergyService::WriteMode /*writeMode*/)
@@ -113,7 +106,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE
}
-void QLowEnergyControllerPrivate::writeDescriptor(
+void QLowEnergyControllerPrivateCommon::writeDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
const QLowEnergyHandle /*charHandle*/,
const QLowEnergyHandle /*descriptorHandle*/,
@@ -122,21 +115,21 @@ void QLowEnergyControllerPrivate::writeDescriptor(
}
-void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &/* params */,
+void QLowEnergyControllerPrivateCommon::startAdvertising(const QLowEnergyAdvertisingParameters &/* params */,
const QLowEnergyAdvertisingData &/* advertisingData */,
const QLowEnergyAdvertisingData &/* scanResponseData */)
{
}
-void QLowEnergyControllerPrivate::stopAdvertising()
+void QLowEnergyControllerPrivateCommon::stopAdvertising()
{
}
-void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters & /* params */)
+void QLowEnergyControllerPrivateCommon::requestConnectionUpdate(const QLowEnergyConnectionParameters & /* params */)
{
}
-void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &/* service */,
+void QLowEnergyControllerPrivateCommon::addToGenericAttributeList(const QLowEnergyServiceData &/* service */,
QLowEnergyHandle /* startHandle */)
{
}
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index 6e866144..54a49b53 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -51,452 +51,62 @@
// We mean it.
//
-#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QLowEnergyControllerPrivate : public QObject
-{
-public:
- // This class is required to make shared pointer machinery and
- // moc (== Obj-C syntax) happy on both OS X and iOS.
-};
-
-QT_END_NAMESPACE
-
-#else
-
#include <qglobal.h>
#include <QtCore/QQueue>
#include <QtCore/QVector>
#include <QtBluetooth/qbluetooth.h>
#include <QtBluetooth/qlowenergycharacteristic.h>
#include "qlowenergycontroller.h"
-#include "qlowenergyserviceprivate_p.h"
-
-#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
-#include <QtBluetooth/QBluetoothSocket>
-#elif defined(QT_ANDROID_BLUETOOTH)
-#include <QtAndroidExtras/QAndroidJniObject>
-#include "android/lowenergynotificationhub_p.h"
-#elif defined(QT_WINRT_BLUETOOTH)
-#include <wrl.h>
-#include <windows.devices.bluetooth.h>
-#endif
-
-#include <functional>
+#include "qlowenergycontrollerbase_p.h"
QT_BEGIN_NAMESPACE
class QLowEnergyServiceData;
-class QTimer;
-
-#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
-class HciManager;
-class LeCmacCalculator;
-class QSocketNotifier;
-class RemoteDeviceManager;
-#elif defined(QT_ANDROID_BLUETOOTH)
-class LowEnergyNotificationHub;
-#elif defined(QT_WINRT_BLUETOOTH)
-class QWinRTLowEnergyServiceHandler;
-#endif
extern void registerQLowEnergyControllerMetaType();
-typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceDataMap;
-class QLeAdvertiser;
-
-class QLowEnergyControllerPrivate : public QObject
+class QLowEnergyControllerPrivateCommon final : public QLowEnergyControllerPrivate
{
Q_OBJECT
- Q_DECLARE_PUBLIC(QLowEnergyController)
public:
- QLowEnergyControllerPrivate();
- ~QLowEnergyControllerPrivate();
+ QLowEnergyControllerPrivateCommon();
+ ~QLowEnergyControllerPrivateCommon() override;
- void init();
+ void init() override;
- void setError(QLowEnergyController::Error newError);
- bool isValidLocalAdapter();
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
- void setState(QLowEnergyController::ControllerState newState);
-
- void connectToDevice();
- void disconnectFromDevice();
-
- void discoverServices();
- void invalidateServices();
-
- void discoverServiceDetails(const QBluetoothUuid &service);
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &service) override;
void startAdvertising(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
- const QLowEnergyAdvertisingData &scanResponseData);
- void stopAdvertising();
-
- void requestConnectionUpdate(const QLowEnergyConnectionParameters &params);
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising() override;
- // misc helpers
- QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(
- QLowEnergyHandle handle);
- QLowEnergyCharacteristic characteristicForHandle(
- QLowEnergyHandle handle);
- QLowEnergyDescriptor descriptorForHandle(
- QLowEnergyHandle handle);
- QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service);
-
-
- quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
- const QByteArray &value,
- bool appendValue);
- quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle,
- QLowEnergyHandle descriptorHandle,
- const QByteArray &value,
- bool appendValue);
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
// read data
void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
- const QLowEnergyHandle charHandle);
+ const QLowEnergyHandle charHandle) override;
void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
- const QLowEnergyHandle descriptorHandle);
+ const QLowEnergyHandle descriptorHandle) override;
// write data
void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
- const QByteArray &newValue, QLowEnergyService::WriteMode mode);
+ const QByteArray &newValue, QLowEnergyService::WriteMode mode) override;
void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue);
+ const QByteArray &newValue) override;
void addToGenericAttributeList(const QLowEnergyServiceData &service,
- QLowEnergyHandle startHandle);
-
- QBluetoothAddress remoteDevice;
- QBluetoothAddress localAdapter;
- QLowEnergyController::Role role;
-
- QString remoteName;
-
- QLowEnergyController::ControllerState state;
- QLowEnergyController::Error error;
- QString errorString;
-
- // list of all found service uuids on remote device
- ServiceDataMap serviceList;
-
- QLowEnergyHandle lastLocalHandle;
- // list of all service uuids on local peripheral device
- ServiceDataMap localServices;
-
- struct Attribute {
- Attribute() : handle(0) {}
-
- QLowEnergyHandle handle;
- QLowEnergyHandle groupEndHandle;
- QLowEnergyCharacteristic::PropertyTypes properties;
- QBluetooth::AttAccessConstraints readConstraints;
- QBluetooth::AttAccessConstraints writeConstraints;
- QBluetoothUuid type;
- QByteArray value;
- int minLength;
- int maxLength;
- };
- QVector<Attribute> localAttributes;
-
- QLowEnergyController::RemoteAddressType addressType;
-
-private:
-#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
- quint16 connectionHandle = 0;
- QBluetoothSocket *l2cpSocket;
- struct Request {
- quint8 command;
- QByteArray payload;
- // TODO reference below is ugly but until we know all commands and their
- // requirements this is WIP
- QVariant reference;
- QVariant reference2;
- };
- QQueue<Request> openRequests;
-
- struct WriteRequest {
- WriteRequest() {}
- WriteRequest(quint16 h, quint16 o, const QByteArray &v)
- : handle(h), valueOffset(o), value(v) {}
- quint16 handle;
- quint16 valueOffset;
- QByteArray value;
- };
- QVector<WriteRequest> openPrepareWriteRequests;
-
- // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true
- QVector<QLowEnergyHandle> scheduledIndications;
- bool indicationInFlight = false;
-
- struct TempClientConfigurationData {
- TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr,
- QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0)
- : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {}
-
- QLowEnergyServicePrivate::DescData *descData;
- QLowEnergyHandle charValueHandle;
- QLowEnergyHandle configHandle;
- };
-
- struct ClientConfigurationData {
- ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0,
- quint16 val = 0)
- : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {}
-
- QLowEnergyHandle charValueHandle;
- QLowEnergyHandle configHandle;
- quint16 configValue;
- bool charValueWasUpdated = false;
- };
- QHash<quint64, QVector<ClientConfigurationData>> clientConfigData;
-
- struct SigningData {
- SigningData() = default;
- SigningData(const quint128 &csrk, quint32 signCounter = quint32(-1))
- : key(csrk), counter(signCounter) {}
-
- quint128 key;
- quint32 counter = quint32(-1);
- };
- QHash<quint64, SigningData> signingData;
- LeCmacCalculator *cmacCalculator = nullptr;
-
- bool requestPending;
- quint16 mtuSize;
- int securityLevelValue;
- bool encryptionChangePending;
- bool receivedMtuExchangeRequest = false;
-
- HciManager *hciManager;
- QLeAdvertiser *advertiser;
- QSocketNotifier *serverSocketNotifier;
- QTimer *requestTimer = nullptr;
- RemoteDeviceManager* device1Manager = nullptr;
-
- /*
- Defines the maximum number of milliseconds the implementation will
- wait for requests that require a response.
-
- This addresses the problem that some non-conformant BTLE devices
- do not implement the request/response system properly. In such cases
- the queue system would hang forever.
-
- Once timeout has been triggered we gracefully continue with the next request.
- Depending on the type of the timed out ATT command we either ignore it
- or artifically trigger an error response to ensure the API gives the
- appropriate response. Potentially this can cause problems when the
- response for the dropped requests arrives very late. That's why a big warning
- is printed about the compromised state when a timeout is triggered.
- */
- int gattRequestTimeout = 20000;
-
- void handleConnectionRequest();
- void closeServerSocket();
-
- bool isBonded() const;
- QVector<TempClientConfigurationData> gatherClientConfigData();
- void storeClientConfigurations();
- void restoreClientConfigurations();
-
- enum SigningKeyType { LocalSigningKey, RemoteSigningKey };
- void loadSigningDataIfNecessary(SigningKeyType keyType);
- void storeSignCounter(SigningKeyType keyType) const;
- QString signingKeySettingsGroup(SigningKeyType keyType) const;
- QString keySettingsFilePath() const;
-
- void sendPacket(const QByteArray &packet);
- void sendNextPendingRequest();
- void processReply(const Request &request, const QByteArray &reply);
-
- void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end,
- quint16 type);
- void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData,
- QLowEnergyHandle nextHandle, quint16 attributeType);
- void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor);
- void readServiceValues(const QBluetoothUuid &service,
- bool readCharacteristics);
- void readServiceValuesByOffset(uint handleData, quint16 offset,
- bool isLastValue);
-
- void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid);
- void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData,
- const QList<QLowEnergyHandle> pendingCharHandles,
- QLowEnergyHandle startingHandle);
- void processUnsolicitedReply(const QByteArray &msg);
- void exchangeMTU();
- bool setSecurityLevel(int level);
- int securityLevel() const;
- void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle,
- const QByteArray &newValue,
- bool isCancelation);
- void sendNextPrepareWriteRequest(const QLowEnergyHandle handle,
- const QByteArray &newValue, quint16 offset);
- bool increaseEncryptLevelfRequired(quint8 errorCode);
-
- void resetController();
-
- void handleAdvertisingError();
-
- bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1);
- bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle);
- bool checkHandlePair(quint8 request, QLowEnergyHandle startingHandle,
- QLowEnergyHandle endingHandle);
-
- void handleExchangeMtuRequest(const QByteArray &packet);
- void handleFindInformationRequest(const QByteArray &packet);
- void handleFindByTypeValueRequest(const QByteArray &packet);
- void handleReadByTypeRequest(const QByteArray &packet);
- void handleReadRequest(const QByteArray &packet);
- void handleReadBlobRequest(const QByteArray &packet);
- void handleReadMultipleRequest(const QByteArray &packet);
- void handleReadByGroupTypeRequest(const QByteArray &packet);
- void handleWriteRequestOrCommand(const QByteArray &packet);
- void handlePrepareWriteRequest(const QByteArray &packet);
- void handleExecuteWriteRequest(const QByteArray &packet);
-
- void sendErrorResponse(quint8 request, quint16 handle, quint8 code);
-
- using ElemWriter = std::function<void(const Attribute &, char *&)>;
- void sendListResponse(const QByteArray &packetStart, int elemSize,
- const QVector<Attribute> &attributes, const ElemWriter &elemWriter);
-
- void sendNotification(QLowEnergyHandle handle);
- void sendIndication(QLowEnergyHandle handle);
- void sendNotificationOrIndication(quint8 opCode, QLowEnergyHandle handle);
- void sendNextIndication();
-
- void ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int(const Attribute &)> &getSize);
- void ensureUniformUuidSizes(QVector<Attribute> &attributes);
- void ensureUniformValueSizes(QVector<Attribute> &attributes);
-
- using AttributePredicate = std::function<bool(const Attribute &)>;
- QVector<Attribute> getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle,
- const AttributePredicate &attributePredicate = [](const Attribute &) { return true; });
-
- int checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type);
- int checkReadPermissions(const Attribute &attr);
- int checkReadPermissions(QVector<Attribute> &attributes);
-
- bool verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter,
- quint64 expectedMac);
-
- void updateLocalAttributeValue(
- QLowEnergyHandle handle,
- const QByteArray &value,
- QLowEnergyCharacteristic &characteristic,
- QLowEnergyDescriptor &descriptor);
-
- void writeCharacteristicForPeripheral(
- QLowEnergyServicePrivate::CharData &charData,
- const QByteArray &newValue);
- void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service,
- QLowEnergyHandle charHandle,
- QLowEnergyHandle valueHandle,
- const QByteArray &newValue,
- QLowEnergyService::WriteMode mode);
-
- void writeDescriptorForPeripheral(
- const QSharedPointer<QLowEnergyServicePrivate> &service,
- const QLowEnergyHandle charHandle,
- const QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue);
- void writeDescriptorForCentral(
- const QLowEnergyHandle charHandle,
- const QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue);
-
- void restartRequestTimer();
- void establishL2cpClientSocket();
- void createServicesForCentralIfRequired();
-
-private slots:
- void l2cpConnected();
- void l2cpDisconnected();
- void l2cpErrorChanged(QBluetoothSocket::SocketError);
- void l2cpReadyRead();
- void encryptionChangedEvent(const QBluetoothAddress&, bool);
- void handleGattRequestTimeout();
- void activeConnectionTerminationDone();
-#elif defined(QT_ANDROID_BLUETOOTH)
- LowEnergyNotificationHub *hub;
-
-private slots:
- void connectionUpdated(QLowEnergyController::ControllerState newState,
- QLowEnergyController::Error errorCode);
- void servicesDiscovered(QLowEnergyController::Error errorCode,
- const QString &foundServices);
- void serviceDetailsDiscoveryFinished(const QString& serviceUuid,
- int startHandle, int endHandle);
- void characteristicRead(const QBluetoothUuid &serviceUuid, int handle,
- const QBluetoothUuid &charUuid, int properties,
- const QByteArray& data);
- void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
- int handle, const QBluetoothUuid &descUuid, const QByteArray &data);
- void characteristicWritten(int charHandle, const QByteArray &data,
- QLowEnergyService::ServiceError errorCode);
- void descriptorWritten(int descHandle, const QByteArray &data,
- QLowEnergyService::ServiceError errorCode);
- void serverDescriptorWritten(const QAndroidJniObject &jniDesc, const QByteArray &newValue);
- void characteristicChanged(int charHandle, const QByteArray &data);
- void serverCharacteristicChanged(const QAndroidJniObject &jniChar, const QByteArray &newValue);
- void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode);
- void advertisementError(int errorCode);
-
-private:
- void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState,
- QLowEnergyController::Error errorCode);
- void centralConnectionUpdated(QLowEnergyController::ControllerState newState,
- QLowEnergyController::Error errorCode);
-
-#elif defined(QT_WINRT_BLUETOOTH)
-private slots:
- void characteristicChanged(int charHandle, const QByteArray &data);
-
-private:
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
- EventRegistrationToken mStatusChangedToken;
- struct ValueChangedEntry {
- ValueChangedEntry() {}
- ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c,
- EventRegistrationToken t)
- : characteristic(c)
- , token(t)
- {
- }
-
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> characteristic;
- EventRegistrationToken token;
- };
- QVector<ValueChangedEntry> mValueChangedTokens;
-
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid);
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
-
- void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
-
- void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService);
-#endif
-private:
- QLowEnergyController *q_ptr;
-
+ QLowEnergyHandle startHandle) override;
};
-Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivate::Attribute, Q_MOVABLE_TYPE);
-
QT_END_NAMESPACE
-#endif // QT_OSX_BLUETOOTH || QT_IOS_BLUETOOTH
-
#endif // QLOWENERGYCONTROLLERPRIVATE_P_H
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index 62b8a9d3..917f3790 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -37,12 +37,16 @@
**
****************************************************************************/
-#include "qlowenergycontroller_p.h"
+#include "qlowenergycontroller_winrt_p.h"
+
+#include <QtBluetooth/QLowEnergyCharacteristicData>
+#include <QtBluetooth/QLowEnergyDescriptorData>
#ifdef CLASSIC_APP_BUILD
#define Q_OS_WINRT
#endif
#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QtEndian>
#include <QtCore/QLoggingCategory>
#include <private/qeventdispatcher_winrt_p.h>
@@ -274,18 +278,15 @@ signals:
QLowEnergyHandle startHandle, QLowEnergyHandle endHandle);
};
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
- : QObject(),
- state(QLowEnergyController::UnconnectedState),
- error(QLowEnergyController::NoError)
+QLowEnergyControllerPrivateWinRT::QLowEnergyControllerPrivateWinRT()
+ : QLowEnergyControllerPrivate()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
- qRegisterMetaType<QLowEnergyCharacteristic>();
- qRegisterMetaType<QLowEnergyDescriptor>();
+ registerQLowEnergyControllerMetaType();
}
-QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT()
{
if (mDevice && mStatusChangedToken.value)
mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
@@ -295,11 +296,11 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
entry.characteristic->remove_ValueChanged(entry.token);
}
-void QLowEnergyControllerPrivate::init()
+void QLowEnergyControllerPrivateWinRT::init()
{
}
-void QLowEnergyControllerPrivate::connectToDevice()
+void QLowEnergyControllerPrivateWinRT::connectToDevice()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
Q_Q(QLowEnergyController);
@@ -403,7 +404,17 @@ void QLowEnergyControllerPrivate::connectToDevice()
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IGattReadResult> result;
hr = QWinRTFunctions::await(op, result.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
+ if (hr == E_INVALIDARG) {
+ // E_INVALIDARG happens when user tries to connect to a device that was paired
+ // before but is not available.
+ qCDebug(QT_BT_WINRT) << "Could not obtain characteristic read result that triggers"
+ "device connection. Is the device reachable?";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ } else {
+ Q_ASSERT_SUCCEEDED(hr);
+ }
ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
hr = result->get_Value(&buffer);
Q_ASSERT_SUCCEEDED(hr);
@@ -417,7 +428,7 @@ void QLowEnergyControllerPrivate::connectToDevice()
}
}
-void QLowEnergyControllerPrivate::disconnectFromDevice()
+void QLowEnergyControllerPrivateWinRT::disconnectFromDevice()
{
qCDebug(QT_BT_WINRT) << __FUNCTION__;
Q_Q(QLowEnergyController);
@@ -429,7 +440,7 @@ void QLowEnergyControllerPrivate::disconnectFromDevice()
}
}
-ComPtr<IGattDeviceService> QLowEnergyControllerPrivate::getNativeService(const QBluetoothUuid &serviceUuid)
+ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRT::getNativeService(const QBluetoothUuid &serviceUuid)
{
ComPtr<IGattDeviceService> deviceService;
HRESULT hr;
@@ -439,7 +450,7 @@ ComPtr<IGattDeviceService> QLowEnergyControllerPrivate::getNativeService(const Q
return deviceService;
}
-ComPtr<IGattCharacteristic> QLowEnergyControllerPrivate::getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid)
+ComPtr<IGattCharacteristic> QLowEnergyControllerPrivateWinRT::getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid)
{
ComPtr<IGattDeviceService> service = getNativeService(serviceUuid);
if (!service)
@@ -454,7 +465,7 @@ ComPtr<IGattCharacteristic> QLowEnergyControllerPrivate::getNativeCharacteristic
return characteristic;
}
-void QLowEnergyControllerPrivate::registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid)
+void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid)
{
qCDebug(QT_BT_WINRT) << "Registering characteristic" << charUuid << "in service"
<< serviceUuid << "for value changes";
@@ -487,7 +498,7 @@ void QLowEnergyControllerPrivate::registerForValueChanges(const QBluetoothUuid &
<< serviceUuid << "registered for value changes";
}
-void QLowEnergyControllerPrivate::obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
+void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
ComPtr<IGattDeviceService> service)
{
Q_Q(QLowEnergyController);
@@ -496,7 +507,9 @@ void QLowEnergyControllerPrivate::obtainIncludedServices(QSharedPointer<QLowEner
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVectorView<GattDeviceService *>> includedServices;
hr = service2->GetAllIncludedServices(&includedServices);
- Q_ASSERT_SUCCEEDED(hr);
+ // Some devices return ERROR_ACCESS_DISABLED_BY_POLICY
+ if (FAILED(hr))
+ return;
uint count;
hr = includedServices->get_Size(&count);
@@ -529,7 +542,7 @@ void QLowEnergyControllerPrivate::obtainIncludedServices(QSharedPointer<QLowEner
}
}
-void QLowEnergyControllerPrivate::discoverServices()
+void QLowEnergyControllerPrivateWinRT::discoverServices()
{
Q_Q(QLowEnergyController);
@@ -571,7 +584,7 @@ void QLowEnergyControllerPrivate::discoverServices()
emit q->discoveryFinished();
}
-void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service)
+void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(const QBluetoothUuid &service)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service;
if (!serviceList.contains(service)) {
@@ -595,7 +608,12 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVectorView<GattDeviceService *>> deviceServices;
hr = deviceService2->GetAllIncludedServices(&deviceServices);
- Q_ASSERT_SUCCEEDED(hr);
+ if (FAILED(hr)) { // ERROR_ACCESS_DISABLED_BY_POLICY
+ qCDebug(QT_BT_WINRT) << "Could not obtain included services list for" << service;
+ pointer->setError(QLowEnergyService::UnknownError);
+ pointer->setState(QLowEnergyService::InvalidService);
+ return;
+ }
uint serviceCount;
hr = deviceServices->get_Size(&serviceCount);
Q_ASSERT_SUCCEEDED(hr);
@@ -656,26 +674,33 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s
thread->start();
}
-void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &, const QLowEnergyAdvertisingData &, const QLowEnergyAdvertisingData &)
+void QLowEnergyControllerPrivateWinRT::startAdvertising(const QLowEnergyAdvertisingParameters &, const QLowEnergyAdvertisingData &, const QLowEnergyAdvertisingData &)
{
+ setError(QLowEnergyController::AdvertisingError);
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivate::stopAdvertising()
+void QLowEnergyControllerPrivateWinRT::stopAdvertising()
{
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters &)
+void QLowEnergyControllerPrivateWinRT::requestConnectionUpdate(const QLowEnergyConnectionParameters &)
{
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+void QLowEnergyControllerPrivateWinRT::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle;
Q_ASSERT(!service.isNull());
+ if (role == QLowEnergyController::PeripheralRole) {
+ service->setError(QLowEnergyService::CharacteristicReadError);
+ Q_UNIMPLEMENTED();
+ return;
+ }
+
if (!service->characteristicList.contains(charHandle)) {
qCDebug(QT_BT_WINRT) << charHandle << "could not be found in service" << service->uuid;
service->setError(QLowEnergyService::CharacteristicReadError);
@@ -729,12 +754,18 @@ void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEn
Q_ASSERT_SUCCEEDED(hr);
}
-void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descHandle)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle;
Q_ASSERT(!service.isNull());
+ if (role == QLowEnergyController::PeripheralRole) {
+ service->setError(QLowEnergyService::DescriptorReadError);
+ Q_UNIMPLEMENTED();
+ return;
+ }
+
if (!service->characteristicList.contains(charHandle)) {
qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "in characteristic" << charHandle
<< "cannot be found in service" << service->uuid;
@@ -854,13 +885,18 @@ void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergy
Q_ASSERT_SUCCEEDED(hr);
}
-void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+void QLowEnergyControllerPrivateWinRT::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QByteArray &newValue,
QLowEnergyService::WriteMode mode)
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << newValue << mode;
Q_ASSERT(!service.isNull());
+ if (role == QLowEnergyController::PeripheralRole) {
+ service->setError(QLowEnergyService::CharacteristicWriteError);
+ Q_UNIMPLEMENTED();
+ return;
+ }
if (!service->characteristicList.contains(charHandle)) {
qCDebug(QT_BT_WINRT) << "Characteristic" << charHandle << "cannot be found in service" << service->uuid;
service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -901,7 +937,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE
GattWriteOption option = writeWithResponse ? GattWriteOption_WriteWithResponse : GattWriteOption_WriteWithoutResponse;
hr = characteristic->WriteValueWithOptionAsync(buffer.Get(), option, &writeOp);
Q_ASSERT_SUCCEEDED(hr);
- auto writeCompletedLambda =[charData, charHandle, newValue, service, this]
+ auto writeCompletedLambda =[charData, charHandle, newValue, service, writeWithResponse, this]
(IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
{
if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -927,7 +963,8 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE
// empty.
if (charData.properties & QLowEnergyCharacteristic::Read)
updateValueOfCharacteristic(charHandle, newValue, false);
- emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle), newValue);
+ if (writeWithResponse)
+ emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle), newValue);
return S_OK;
};
hr = writeOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus>>(writeCompletedLambda).Get());
@@ -937,7 +974,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE
Q_ASSERT_SUCCEEDED(hr);
}
-void QLowEnergyControllerPrivate::writeDescriptor(
+void QLowEnergyControllerPrivateWinRT::writeDescriptor(
const QSharedPointer<QLowEnergyServicePrivate> service,
const QLowEnergyHandle charHandle,
const QLowEnergyHandle descHandle,
@@ -945,6 +982,12 @@ void QLowEnergyControllerPrivate::writeDescriptor(
{
qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle << newValue;
Q_ASSERT(!service.isNull());
+ if (role == QLowEnergyController::PeripheralRole) {
+ service->setError(QLowEnergyService::DescriptorWriteError);
+ Q_UNIMPLEMENTED();
+ return;
+ }
+
if (!service->characteristicList.contains(charHandle)) {
qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "in characteristic" << charHandle
<< "could not be found in service" << service->uuid;
@@ -1076,12 +1119,12 @@ void QLowEnergyControllerPrivate::writeDescriptor(
}
-void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle)
+void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle)
{
Q_UNIMPLEMENTED();
}
-void QLowEnergyControllerPrivate::characteristicChanged(
+void QLowEnergyControllerPrivateWinRT::characteristicChanged(
int charHandle, const QByteArray &data)
{
QSharedPointer<QLowEnergyServicePrivate> service =
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
new file mode 100644
index 00000000..783a71fa
--- /dev/null
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QLOWENERGYCONTROLLERPRIVATEWINRT_P_H
+#define QLOWENERGYCONTROLLERPRIVATEWINRT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include <QtCore/QQueue>
+#include <QtCore/QVector>
+#include <QtBluetooth/qbluetooth.h>
+#include <QtBluetooth/qlowenergycharacteristic.h>
+#include <QtBluetooth/qlowenergyservicedata.h>
+#include "qlowenergycontroller.h"
+#include "qlowenergycontrollerbase_p.h"
+
+#include <wrl.h>
+#include <windows.devices.bluetooth.h>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyServiceData;
+class QTimer;
+class QWinRTLowEnergyServiceHandler;
+
+extern void registerQLowEnergyControllerMetaType();
+
+class QLowEnergyControllerPrivateWinRT final : public QLowEnergyControllerPrivate
+{
+ Q_OBJECT
+public:
+ QLowEnergyControllerPrivateWinRT();
+ ~QLowEnergyControllerPrivateWinRT() override;
+
+ void init() override;
+
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &service) override;
+
+ void startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising() override;
+
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
+
+ // read data
+ void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle) override;
+ void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle) override;
+
+ // write data
+ void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QByteArray &newValue, QLowEnergyService::WriteMode mode) override;
+ void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue) override;
+
+ void addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle) override;
+
+private slots:
+ void characteristicChanged(int charHandle, const QByteArray &data);
+
+private:
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
+ EventRegistrationToken mStatusChangedToken;
+ struct ValueChangedEntry {
+ ValueChangedEntry() {}
+ ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c,
+ EventRegistrationToken t)
+ : characteristic(c)
+ , token(t)
+ {
+ }
+
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> characteristic;
+ EventRegistrationToken token;
+ };
+ QVector<ValueChangedEntry> mValueChangedTokens;
+
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid);
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
+
+ void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
+
+ void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService);
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOWENERGYCONTROLLERPRIVATEWINRT_P_H
diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp
new file mode 100644
index 00000000..c7b9ec0b
--- /dev/null
+++ b/src/bluetooth/qlowenergycontrollerbase.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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 "qlowenergycontrollerbase_p.h"
+
+#include <QtCore/QLoggingCategory>
+
+#include <QtBluetooth/QBluetoothLocalDevice>
+#include <QtBluetooth/QLowEnergyCharacteristicData>
+#include <QtBluetooth/QLowEnergyDescriptorData>
+#include <QtBluetooth/QLowEnergyServiceData>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_BT)
+
+QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
+ : QObject()
+{
+}
+
+QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
+{
+}
+
+bool QLowEnergyControllerPrivate::isValidLocalAdapter()
+{
+#ifdef QT_WINRT_BLUETOOTH
+ return true;
+#endif
+ if (localAdapter.isNull())
+ return false;
+
+ const QList<QBluetoothHostInfo> foundAdapters = QBluetoothLocalDevice::allDevices();
+ bool adapterFound = false;
+
+ foreach (const QBluetoothHostInfo &info, foundAdapters) {
+ if (info.address() == localAdapter) {
+ adapterFound = true;
+ break;
+ }
+ }
+
+ return adapterFound;
+}
+
+
+void QLowEnergyControllerPrivate::setError(
+ QLowEnergyController::Error newError)
+{
+ Q_Q(QLowEnergyController);
+ error = newError;
+
+ switch (newError) {
+ case QLowEnergyController::UnknownRemoteDeviceError:
+ errorString = QLowEnergyController::tr("Remote device cannot be found");
+ break;
+ case QLowEnergyController::InvalidBluetoothAdapterError:
+ errorString = QLowEnergyController::tr("Cannot find local adapter");
+ break;
+ case QLowEnergyController::NetworkError:
+ errorString = QLowEnergyController::tr("Error occurred during connection I/O");
+ break;
+ case QLowEnergyController::ConnectionError:
+ errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device.");
+ break;
+ case QLowEnergyController::AdvertisingError:
+ errorString = QLowEnergyController::tr("Error occurred trying to start advertising");
+ break;
+ case QLowEnergyController::RemoteHostClosedError:
+ errorString = QLowEnergyController::tr("Remote device closed the connection");
+ break;
+ case QLowEnergyController::NoError:
+ return;
+ default:
+ case QLowEnergyController::UnknownError:
+ errorString = QLowEnergyController::tr("Unknown Error");
+ break;
+ }
+
+ emit q->error(newError);
+}
+
+void QLowEnergyControllerPrivate::setState(
+ QLowEnergyController::ControllerState newState)
+{
+ Q_Q(QLowEnergyController);
+ if (state == newState)
+ return;
+
+ state = newState;
+ if (state == QLowEnergyController::UnconnectedState
+ && role == QLowEnergyController::PeripheralRole) {
+ remoteDevice.clear();
+ }
+ emit q->stateChanged(state);
+}
+
+QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivate::serviceForHandle(
+ QLowEnergyHandle handle)
+{
+ ServiceDataMap &currentList = serviceList;
+ if (role == QLowEnergyController::PeripheralRole)
+ currentList = localServices;
+
+ const QList<QSharedPointer<QLowEnergyServicePrivate>> values = currentList.values();
+ for (auto service: values)
+ if (service->startHandle <= handle && handle <= service->endHandle)
+ return service;
+
+ return QSharedPointer<QLowEnergyServicePrivate>();
+}
+
+/*!
+ Returns a valid characteristic if the given handle is the
+ handle of the characteristic itself or one of its descriptors
+ */
+QLowEnergyCharacteristic QLowEnergyControllerPrivate::characteristicForHandle(
+ QLowEnergyHandle handle)
+{
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(handle);
+ if (service.isNull())
+ return QLowEnergyCharacteristic();
+
+ if (service->characteristicList.isEmpty())
+ return QLowEnergyCharacteristic();
+
+ // check whether it is the handle of a characteristic header
+ if (service->characteristicList.contains(handle))
+ return QLowEnergyCharacteristic(service, handle);
+
+ // check whether it is the handle of the characteristic value or its descriptors
+ QList<QLowEnergyHandle> charHandles = service->characteristicList.keys();
+ std::sort(charHandles.begin(), charHandles.end());
+ for (int i = charHandles.size() - 1; i >= 0; i--) {
+ if (charHandles.at(i) > handle)
+ continue;
+
+ return QLowEnergyCharacteristic(service, charHandles.at(i));
+ }
+
+ return QLowEnergyCharacteristic();
+}
+
+/*!
+ Returns a valid descriptor if \a handle belongs to a descriptor;
+ otherwise an invalid one.
+ */
+QLowEnergyDescriptor QLowEnergyControllerPrivate::descriptorForHandle(
+ QLowEnergyHandle handle)
+{
+ const QLowEnergyCharacteristic matchingChar = characteristicForHandle(handle);
+ if (!matchingChar.isValid())
+ return QLowEnergyDescriptor();
+
+ const QLowEnergyServicePrivate::CharData charData = matchingChar.
+ d_ptr->characteristicList[matchingChar.attributeHandle()];
+
+ if (charData.descriptorList.contains(handle))
+ return QLowEnergyDescriptor(matchingChar.d_ptr, matchingChar.attributeHandle(),
+ handle);
+
+ return QLowEnergyDescriptor();
+}
+
+/*!
+ Returns the length of the updated characteristic value.
+ */
+quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic(
+ QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue)
+{
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
+ if (!service.isNull()) {
+ CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle);
+ if (charIt != service->characteristicList.end()) {
+ QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
+
+ if (appendValue)
+ charDetails.value += value;
+ else
+ charDetails.value = value;
+
+ return charDetails.value.size();
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ Returns the length of the updated descriptor value.
+ */
+quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor(
+ QLowEnergyHandle charHandle, QLowEnergyHandle descriptorHandle,
+ const QByteArray &value, bool appendValue)
+{
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
+ if (!service.isNull()) {
+ CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle);
+ if (charIt != service->characteristicList.end()) {
+ QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
+
+ DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle);
+ if (descIt != charDetails.descriptorList.end()) {
+ QLowEnergyServicePrivate::DescData &descDetails = descIt.value();
+
+ if (appendValue)
+ descDetails.value += value;
+ else
+ descDetails.value = value;
+
+ return descDetails.value.size();
+ }
+ }
+ }
+
+ return 0;
+}
+
+void QLowEnergyControllerPrivate::invalidateServices()
+{
+ foreach (const QSharedPointer<QLowEnergyServicePrivate> service, serviceList.values()) {
+ service->setController(0);
+ service->setState(QLowEnergyService::InvalidService);
+ }
+
+ serviceList.clear();
+ localServices.clear();
+ lastLocalHandle = {};
+}
+
+QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper(
+ const QLowEnergyServiceData &service)
+{
+ // Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit).
+ // Since this is not mandatory, we ignore it here and let the caller take responsibility
+ // for it.
+
+ const auto servicePrivate = QSharedPointer<QLowEnergyServicePrivate>::create();
+ servicePrivate->state = QLowEnergyService::LocalService;
+ servicePrivate->setController(this);
+ servicePrivate->uuid = service.uuid();
+ servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary
+ ? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService;
+ foreach (QLowEnergyService * const includedService, service.includedServices()) {
+ servicePrivate->includedServices << includedService->serviceUuid();
+ includedService->d_ptr->type |= QLowEnergyService::IncludedService;
+ }
+
+ // Spec v4.2, Vol 3, Part G, Section 3.
+ const QLowEnergyHandle oldLastHandle = this->lastLocalHandle;
+ servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration.
+ this->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations.
+ foreach (const QLowEnergyCharacteristicData &cd, service.characteristics()) {
+ const QLowEnergyHandle declHandle = ++this->lastLocalHandle;
+ QLowEnergyServicePrivate::CharData charData;
+ charData.valueHandle = ++this->lastLocalHandle;
+ charData.uuid = cd.uuid();
+ charData.properties = cd.properties();
+ charData.value = cd.value();
+ foreach (const QLowEnergyDescriptorData &dd, cd.descriptors()) {
+ QLowEnergyServicePrivate::DescData descData;
+ descData.uuid = dd.uuid();
+ descData.value = dd.value();
+ charData.descriptorList.insert(++this->lastLocalHandle, descData);
+ }
+ servicePrivate->characteristicList.insert(declHandle, charData);
+ }
+ servicePrivate->endHandle = this->lastLocalHandle;
+ const bool handleOverflow = this->lastLocalHandle <= oldLastHandle;
+ if (handleOverflow) {
+ qCWarning(QT_BT) << "Not enough attribute handles left to create this service";
+ this->lastLocalHandle = oldLastHandle;
+ return nullptr;
+ }
+
+ if (localServices.contains(servicePrivate->uuid)) {
+ qWarning() << "Overriding existing local service with uuid"
+ << servicePrivate->uuid;
+ }
+ this->localServices.insert(servicePrivate->uuid, servicePrivate);
+
+ this->addToGenericAttributeList(service, servicePrivate->startHandle);
+ return new QLowEnergyService(servicePrivate);
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontrollerbase_p.h b/src/bluetooth/qlowenergycontrollerbase_p.h
new file mode 100644
index 00000000..a8d1c676
--- /dev/null
+++ b/src/bluetooth/qlowenergycontrollerbase_p.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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: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 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 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.
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QLOWENERGYCONTROLLERPRIVATEBASE_P_H
+#define QLOWENERGYCONTROLLERPRIVATEBASE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyControllerPrivate : public QObject
+{
+public:
+ // This class is required to make shared pointer machinery and
+ // moc (== Obj-C syntax) happy on both OS X and iOS.
+};
+
+QT_END_NAMESPACE
+
+#else
+
+#include <qglobal.h>
+#include <QtCore/qobject.h>
+
+#include <QtBluetooth/qlowenergycontroller.h>
+
+#include "qlowenergyserviceprivate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceDataMap;
+
+class QLowEnergyControllerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ // This class is required to enable selection of multiple
+ // alternative QLowEnergyControllerPrivate implementations on BlueZ.
+ // Bluez has a low level ATT protocol stack implementation and a DBus
+ // implementation.
+
+ QLowEnergyControllerPrivate();
+ virtual ~QLowEnergyControllerPrivate();
+
+ // interface definition
+ virtual void init() = 0;
+ virtual void connectToDevice() = 0;
+ virtual void disconnectFromDevice() = 0;
+
+ virtual void discoverServices() = 0;
+ virtual void discoverServiceDetails(const QBluetoothUuid &/*service*/) = 0;
+
+ virtual void readCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/) = 0;
+ virtual void readDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QLowEnergyHandle /*descriptorHandle*/) = 0;
+
+ virtual void writeCharacteristic(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QByteArray &/*newValue*/,
+ QLowEnergyService::WriteMode /*writeMode*/) = 0;
+ virtual void writeDescriptor(
+ const QSharedPointer<QLowEnergyServicePrivate> /*service*/,
+ const QLowEnergyHandle /*charHandle*/,
+ const QLowEnergyHandle /*descriptorHandle*/,
+ const QByteArray &/*newValue*/) = 0;
+
+ virtual void startAdvertising(
+ const QLowEnergyAdvertisingParameters &/* params */,
+ const QLowEnergyAdvertisingData &/* advertisingData */,
+ const QLowEnergyAdvertisingData &/* scanResponseData */) = 0;
+ virtual void stopAdvertising() = 0;
+
+ virtual void requestConnectionUpdate(
+ const QLowEnergyConnectionParameters & /* params */) = 0;
+ virtual void addToGenericAttributeList(
+ const QLowEnergyServiceData &/* service */,
+ QLowEnergyHandle /* startHandle */) = 0;
+
+
+ virtual QLowEnergyService *addServiceHelper(
+ const QLowEnergyServiceData &service);
+
+
+ // common backend methods
+ bool isValidLocalAdapter();
+ void setError(QLowEnergyController::Error newError);
+ void setState(QLowEnergyController::ControllerState newState);
+
+ // public variables
+ QLowEnergyController::Role role;
+ QLowEnergyController::RemoteAddressType addressType;
+
+ // list of all found service uuids on remote device
+ ServiceDataMap serviceList;
+ // list of all found service uuids on local peripheral device
+ ServiceDataMap localServices;
+
+ //common helper functions
+ QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(QLowEnergyHandle handle);
+ QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle handle);
+ QLowEnergyDescriptor descriptorForHandle(QLowEnergyHandle handle);
+ quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
+ const QByteArray &value,
+ bool appendValue);
+ quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle,
+ QLowEnergyHandle descriptorHandle,
+ const QByteArray &value,
+ bool appendValue);
+ void invalidateServices();
+
+protected:
+ QLowEnergyController::ControllerState state = QLowEnergyController::UnconnectedState;
+ QLowEnergyController::Error error = QLowEnergyController::NoError;
+ QString errorString;
+
+ QBluetoothAddress remoteDevice;
+ QBluetoothAddress localAdapter;
+
+ QLowEnergyHandle lastLocalHandle{};
+
+ QString remoteName; // device name of the remote
+
+ Q_DECLARE_PUBLIC(QLowEnergyController)
+ QLowEnergyController *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif //defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
+
+#endif // QLOWENERGYCONTROLLERPRIVATEBASE_P_H
diff --git a/src/bluetooth/qlowenergydescriptor.cpp b/src/bluetooth/qlowenergydescriptor.cpp
index 37a8f619..15859f17 100644
--- a/src/bluetooth/qlowenergydescriptor.cpp
+++ b/src/bluetooth/qlowenergydescriptor.cpp
@@ -54,14 +54,14 @@ QT_BEGIN_NAMESPACE
QLowEnergyDescriptor provides information about a Bluetooth Low Energy
descriptor's \l name(), \l uuid(), \l value() and \l handle(). Descriptors are
encapsulated by Bluetooth Low Energy characteristics and provide additional
- centextual information about the characteristic (data format, notification activation
+ contextual information about the characteristic (data format, notification activation
and so on).
The descriptor value may be written via the \l QLowEnergyService instance
that manages the service to which this descriptor belongs. The
\l {QLowEnergyService::writeDescriptor()} function writes the new value.
The \l {QLowEnergyService::descriptorWritten()} signal
- is emitted upon success. The cahced \l value() of this object is updated accordingly.
+ is emitted upon success. The cached \l value() of this object is updated accordingly.
\sa QLowEnergyService, QLowEnergyCharacteristic
*/
diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h
index 9e71fc56..fca1be76 100644
--- a/src/bluetooth/qlowenergydescriptor.h
+++ b/src/bluetooth/qlowenergydescriptor.h
@@ -79,7 +79,12 @@ protected:
friend class QLowEnergyCharacteristic;
friend class QLowEnergyService;
friend class QLowEnergyControllerPrivate;
+ friend class QLowEnergyControllerPrivateAndroid;
+ friend class QLowEnergyControllerPrivateBluez;
+ friend class QLowEnergyControllerPrivateBluezDBus;
+ friend class QLowEnergyControllerPrivateCommon;
friend class QLowEnergyControllerPrivateOSX;
+ friend class QLowEnergyControllerPrivateWinRT;
QLowEnergyDescriptorPrivate *data;
QLowEnergyDescriptor(QSharedPointer<QLowEnergyServicePrivate> p,
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 35a3a7d0..357d3901 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -44,7 +44,7 @@
#include <algorithm>
-#include "qlowenergycontroller_p.h"
+#include "qlowenergycontrollerbase_p.h"
#include "qlowenergyserviceprivate_p.h"
QT_BEGIN_NAMESPACE
@@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE
\image peripheral-structure.png Structure of a generic peripheral
- A characteristic is the principle information carrier. It has a
+ A characteristic is the principal information carrier. It has a
\l {QLowEnergyCharacteristic::value()}{value()} and
\l {QLowEnergyCharacteristic::value()}{properties()}
describing the access permissions for the value. The general purpose
@@ -380,23 +380,21 @@ QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
qRegisterMetaType<QLowEnergyService::ServiceError>();
qRegisterMetaType<QLowEnergyService::ServiceType>();
qRegisterMetaType<QLowEnergyService::WriteMode>();
- qRegisterMetaType<QLowEnergyCharacteristic>();
- qRegisterMetaType<QLowEnergyDescriptor>();
-
- connect(p.data(), SIGNAL(error(QLowEnergyService::ServiceError)),
- this, SIGNAL(error(QLowEnergyService::ServiceError)));
- connect(p.data(), SIGNAL(stateChanged(QLowEnergyService::ServiceState)),
- this, SIGNAL(stateChanged(QLowEnergyService::ServiceState)));
- connect(p.data(), SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),
- this, SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)));
- connect(p.data(), SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)),
- this, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)));
- connect(p.data(), SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)),
- this, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)));
- connect(p.data(), SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)),
- this, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
- connect(p.data(), SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)),
- this, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
+
+ connect(p.data(), &QLowEnergyServicePrivate::error,
+ this, QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error));
+ connect(p.data(), &QLowEnergyServicePrivate::stateChanged,
+ this, &QLowEnergyService::stateChanged);
+ connect(p.data(), &QLowEnergyServicePrivate::characteristicChanged,
+ this, &QLowEnergyService::characteristicChanged);
+ connect(p.data(), &QLowEnergyServicePrivate::characteristicWritten,
+ this, &QLowEnergyService::characteristicWritten);
+ connect(p.data(), &QLowEnergyServicePrivate::descriptorWritten,
+ this, &QLowEnergyService::descriptorWritten);
+ connect(p.data(), &QLowEnergyServicePrivate::characteristicRead,
+ this, &QLowEnergyService::characteristicRead);
+ connect(p.data(), &QLowEnergyServicePrivate::descriptorRead,
+ this, &QLowEnergyService::descriptorRead);
}
/*!
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index 3f6cfd88..9de65a84 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -47,7 +47,6 @@
QT_BEGIN_NAMESPACE
class QLowEnergyServicePrivate;
-class QLowEnergyControllerPrivate;
class Q_BLUETOOTH_EXPORT QLowEnergyService : public QObject
{
Q_OBJECT
@@ -135,6 +134,8 @@ private:
// QLowEnergyController is the factory for this class
friend class QLowEnergyController;
friend class QLowEnergyControllerPrivate;
+ friend class QLowEnergyControllerPrivateBluez;
+ friend class QLowEnergyControllerPrivateAndroid;
QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
QObject *parent = nullptr);
};
diff --git a/src/bluetooth/qlowenergyserviceprivate.cpp b/src/bluetooth/qlowenergyserviceprivate.cpp
index 83724d4e..0b8d8be0 100644
--- a/src/bluetooth/qlowenergyserviceprivate.cpp
+++ b/src/bluetooth/qlowenergyserviceprivate.cpp
@@ -39,7 +39,7 @@
#include "qlowenergyserviceprivate_p.h"
-#include "qlowenergycontroller_p.h"
+#include "qlowenergycontrollerbase_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qtbluetoothglobal_p.h b/src/bluetooth/qtbluetoothglobal_p.h
index ffbfc4fe..59944593 100644
--- a/src/bluetooth/qtbluetoothglobal_p.h
+++ b/src/bluetooth/qtbluetoothglobal_p.h
@@ -56,4 +56,10 @@
#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/private/qtbluetooth-config_p.h>
+QT_BEGIN_NAMESPACE
+
+#define Q_BLUETOOTH_PRIVATE_EXPORT Q_BLUETOOTH_EXPORT
+
+QT_END_NAMESPACE
+
#endif // QTBLUETOOTHGLOBAL_P_H
diff --git a/src/imports/bluetooth/plugin.cpp b/src/imports/bluetooth/plugin.cpp
index 2a152e32..1e9737c6 100644
--- a/src/imports/bluetooth/plugin.cpp
+++ b/src/imports/bluetooth/plugin.cpp
@@ -45,13 +45,6 @@
#include "qdeclarativebluetoothservice_p.h"
#include "qdeclarativebluetoothsocket_p.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtBluetooth);
-#endif
-}
-
QT_USE_NAMESPACE
class QBluetoothQmlPlugin : public QQmlExtensionPlugin
@@ -59,7 +52,7 @@ class QBluetoothQmlPlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QBluetoothQmlPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QBluetoothQmlPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri)
{
// @uri QtBluetooth
@@ -81,10 +74,8 @@ public:
qmlRegisterType<QDeclarativeBluetoothService >(uri, major, minor, "BluetoothService");
qmlRegisterType<QDeclarativeBluetoothSocket >(uri, major, minor, "BluetoothSocket");
- // Register the 5.9 types
- // introduces 5.9 version, other existing 5.2 exports become automatically available under 5.2-5.8
- minor = 9;
- qmlRegisterType<QDeclarativeBluetoothDiscoveryModel >(uri, major, minor, "BluetoothDiscoveryModel");
+ // Register the latest Qt version as QML type version
+ qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
}
};
diff --git a/src/imports/bluetooth/plugins.qmltypes b/src/imports/bluetooth/plugins.qmltypes
index e23f8740..a22b950a 100644
--- a/src/imports/bluetooth/plugins.qmltypes
+++ b/src/imports/bluetooth/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtBluetooth 5.9'
+// 'qmlplugindump -nonrelocatable QtBluetooth 5.11'
Module {
dependencies: ["QtQuick 2.8"]
@@ -13,10 +13,9 @@ Module {
prototype: "QAbstractListModel"
exports: [
"QtBluetooth/BluetoothDiscoveryModel 5.0",
- "QtBluetooth/BluetoothDiscoveryModel 5.2",
- "QtBluetooth/BluetoothDiscoveryModel 5.9"
+ "QtBluetooth/BluetoothDiscoveryModel 5.2"
]
- exportMetaObjectRevisions: [0, 0, 0]
+ exportMetaObjectRevisions: [0, 0]
Enum {
name: "DiscoveryMode"
values: {
@@ -93,6 +92,7 @@ Module {
values: {
"NoError": -2,
"UnknownSocketError": -1,
+ "RemoteHostClosedError": 1,
"HostNotFoundError": 2,
"ServiceNotFoundError": 9,
"NetworkError": 7,
diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
index f2486e81..fc1accbd 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
+++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp
@@ -142,22 +142,30 @@ QDeclarativeBluetoothDiscoveryModel::QDeclarativeBluetoothDiscoveryModel(QObject
d(new QDeclarativeBluetoothDiscoveryModelPrivate)
{
d->m_deviceAgent = new QBluetoothDeviceDiscoveryAgent(this);
- connect(d->m_deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
- this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
- connect(d->m_deviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
- connect(d->m_deviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
- connect(d->m_deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
- this, SLOT(errorDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::Error)));
- d->m_deviceAgent->setObjectName("DeviceDiscoveryAgent");
+ connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
+ this, QOverload<const QBluetoothDeviceInfo&>::of(&QDeclarativeBluetoothDiscoveryModel::deviceDiscovered));
+ connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::finished,
+ this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery);
+ connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::canceled,
+ this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery);
+ connect(d->m_deviceAgent,
+ QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
+ this,
+ &QDeclarativeBluetoothDiscoveryModel::errorDeviceDiscovery);
+ d->m_deviceAgent->setObjectName(QStringLiteral("DeviceDiscoveryAgent"));
d->m_serviceAgent = new QBluetoothServiceDiscoveryAgent(this);
- connect(d->m_serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
- this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
- connect(d->m_serviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
- connect(d->m_serviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
- connect(d->m_serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),
- this, SLOT(errorDiscovery(QBluetoothServiceDiscoveryAgent::Error)));
- d->m_serviceAgent->setObjectName("ServiceDiscoveryAgent");
+ connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered,
+ this, QOverload<const QBluetoothServiceInfo&>::of(&QDeclarativeBluetoothDiscoveryModel::serviceDiscovered));
+ connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::finished,
+ this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery);
+ connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::canceled,
+ this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery);
+ connect(d->m_serviceAgent,
+ QOverload<QBluetoothServiceDiscoveryAgent::Error>::of(&QBluetoothServiceDiscoveryAgent::error),
+ this,
+ &QDeclarativeBluetoothDiscoveryModel::errorDiscovery);
+ d->m_serviceAgent->setObjectName(QStringLiteral("ServiceDiscoveryAgent"));
QHash<int, QByteArray> roleNames;
roleNames = QAbstractItemModel::roleNames();
diff --git a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp
index efbf217b..48c9da9a 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp
+++ b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp
@@ -297,7 +297,8 @@ void QDeclarativeBluetoothService::setRegistered(bool registered)
}
d->m_server = server;
- connect(d->m_server, SIGNAL(newConnection()), this, SLOT(new_connection()));
+ connect(d->m_server, &QBluetoothServer::newConnection,
+ this, &QDeclarativeBluetoothService::new_connection);
d->m_service->setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010);
diff --git a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
index 0d5a5eae..07de35bc 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
+++ b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
@@ -112,11 +112,16 @@ public:
m_socket = new QBluetoothSocket(socketProtocol);
m_socket->connectToService(*m_service->serviceInfo());
- QObject::connect(m_socket, SIGNAL(connected()), m_dbs, SLOT(socket_connected()));
- QObject::connect(m_socket, SIGNAL(disconnected()), m_dbs, SLOT(socket_disconnected()));
- QObject::connect(m_socket, SIGNAL(error(QBluetoothSocket::SocketError)), m_dbs, SLOT(socket_error(QBluetoothSocket::SocketError)));
- QObject::connect(m_socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), m_dbs, SLOT(socket_state(QBluetoothSocket::SocketState)));
- QObject::connect(m_socket, SIGNAL(readyRead()), m_dbs, SLOT(socket_readyRead()));
+ QObject::connect(m_socket, &QBluetoothSocket::connected,
+ m_dbs, &QDeclarativeBluetoothSocket::socket_connected);
+ QObject::connect(m_socket, &QBluetoothSocket::disconnected,
+ m_dbs, &QDeclarativeBluetoothSocket::socket_disconnected);
+ QObject::connect(m_socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
+ m_dbs, &QDeclarativeBluetoothSocket::socket_error);
+ QObject::connect(m_socket, &QBluetoothSocket::stateChanged,
+ m_dbs, &QDeclarativeBluetoothSocket::socket_state);
+ QObject::connect(m_socket, &QIODevice::readyRead,
+ m_dbs, &QDeclarativeBluetoothSocket::socket_readyRead);
}
QDeclarativeBluetoothSocket *m_dbs;
@@ -363,11 +368,16 @@ void QDeclarativeBluetoothSocket::newSocket(QBluetoothSocket *socket, QDeclarati
d->m_componentCompleted = true;
d->m_error = NoError;
- QObject::connect(socket, SIGNAL(connected()), this, SLOT(socket_connected()));
- QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(socket_disconnected()));
- QObject::connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socket_error(QBluetoothSocket::SocketError)));
- QObject::connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socket_state(QBluetoothSocket::SocketState)));
- QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(socket_readyRead()));
+ QObject::connect(socket, &QBluetoothSocket::connected,
+ this, &QDeclarativeBluetoothSocket::socket_connected);
+ QObject::connect(socket, &QBluetoothSocket::disconnected,
+ this, &QDeclarativeBluetoothSocket::socket_disconnected);
+ QObject::connect(socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
+ this, &QDeclarativeBluetoothSocket::socket_error);
+ QObject::connect(socket, &QBluetoothSocket::stateChanged,
+ this, &QDeclarativeBluetoothSocket::socket_state);
+ QObject::connect(socket, &QIODevice::readyRead,
+ this, &QDeclarativeBluetoothSocket::socket_readyRead);
socket_state(socket->state());
diff --git a/src/imports/nfc/plugin.cpp b/src/imports/nfc/plugin.cpp
index 53febda2..3a6806fa 100644
--- a/src/imports/nfc/plugin.cpp
+++ b/src/imports/nfc/plugin.cpp
@@ -47,13 +47,6 @@
#include "qdeclarativendefurirecord_p.h"
#include "qdeclarativendefmimerecord_p.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtNfc);
-#endif
-}
-
QT_USE_NAMESPACE
class QNfcQmlPlugin : public QQmlExtensionPlugin
@@ -62,7 +55,7 @@ class QNfcQmlPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QNfcQmlPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QNfcQmlPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri)
{
Q_ASSERT(uri == QStringLiteral("QtNfc"));
@@ -98,10 +91,9 @@ public:
minor = 5;
qmlRegisterType<QDeclarativeNearField, 1>(uri, major, minor, "NearField");
- // Register the 5.6 - 5.9 types
- minor = 9;
- qmlRegisterType<QDeclarativeNearField, 1>(uri, major, minor, "NearField");
+ // Register the latest Qt version as QML type version
+ qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
}
};
diff --git a/src/imports/nfc/plugins.qmltypes b/src/imports/nfc/plugins.qmltypes
index 45cf53b8..4f723967 100644
--- a/src/imports/nfc/plugins.qmltypes
+++ b/src/imports/nfc/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtNfc 5.9'
+// 'qmlplugindump -nonrelocatable QtNfc 5.11'
Module {
dependencies: ["QtQuick 2.8"]
@@ -57,10 +57,9 @@ Module {
"QtNfc/NearField 5.0",
"QtNfc/NearField 5.2",
"QtNfc/NearField 5.4",
- "QtNfc/NearField 5.5",
- "QtNfc/NearField 5.9"
+ "QtNfc/NearField 5.5"
]
- exportMetaObjectRevisions: [0, 0, 0, 1, 1]
+ exportMetaObjectRevisions: [0, 0, 0, 1]
Property { name: "messageRecords"; type: "QQmlNdefRecord"; isList: true; isReadonly: true }
Property { name: "filter"; type: "QDeclarativeNdefFilter"; isList: true; isReadonly: true }
Property { name: "orderMatch"; type: "bool" }
diff --git a/src/imports/nfc/qdeclarativendeffilter.cpp b/src/imports/nfc/qdeclarativendeffilter.cpp
index 010be47f..6cbda747 100644
--- a/src/imports/nfc/qdeclarativendeffilter.cpp
+++ b/src/imports/nfc/qdeclarativendeffilter.cpp
@@ -78,7 +78,7 @@
/*!
\qmlproperty QQmlNdefRecord::TypeNameFormat NdefFilter::typeNameFormat
- This property holds the NDEF record name format type \enum QQmlNdefRecord::TypeNameFormat.
+ This property holds the NDEF record name format type \l QQmlNdefRecord::TypeNameFormat.
*/
/*!
diff --git a/src/nfc/android/androidjninfc.cpp b/src/nfc/android/androidjninfc.cpp
index f21d3b08..9a1c5227 100644
--- a/src/nfc/android/androidjninfc.cpp
+++ b/src/nfc/android/androidjninfc.cpp
@@ -63,6 +63,11 @@ bool isAvailable()
return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"isAvailable");
}
+bool isSupported()
+{
+ return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"isSupported");
+}
+
bool stopDiscovery()
{
return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"stop");
diff --git a/src/nfc/android/androidjninfc_p.h b/src/nfc/android/androidjninfc_p.h
index 746a93ee..60e9a107 100644
--- a/src/nfc/android/androidjninfc_p.h
+++ b/src/nfc/android/androidjninfc_p.h
@@ -71,6 +71,7 @@ bool startDiscovery();
bool stopDiscovery();
QAndroidJniObject getStartIntent();
bool isAvailable();
+bool isSupported();
bool registerListener(AndroidNfcListenerInterface *listener);
bool unregisterListener(AndroidNfcListenerInterface *listener);
QAndroidJniObject getTag(const QAndroidJniObject &intent);
diff --git a/src/nfc/doc/snippets/doc_src_qtnfc.cpp b/src/nfc/doc/snippets/doc_src_qtnfc.cpp
index f4d7f91a..760d65fd 100644
--- a/src/nfc/doc/snippets/doc_src_qtnfc.cpp
+++ b/src/nfc/doc/snippets/doc_src_qtnfc.cpp
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2013 Aaron McCarthy <mccarthy.aaron@gmail.com>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/snippets/doc_src_qtnfc.qml b/src/nfc/doc/snippets/doc_src_qtnfc.qml
index 65efee56..78f7f83d 100644
--- a/src/nfc/doc/snippets/doc_src_qtnfc.qml
+++ b/src/nfc/doc/snippets/doc_src_qtnfc.qml
@@ -1,13 +1,23 @@
/****************************************************************************
**
** Copyright (C) 2013 Aaron McCarthy <mccarthy.aaron@gmail.com>
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/snippets/foorecord.cpp b/src/nfc/doc/snippets/foorecord.cpp
index 14a83af3..4fecd712 100644
--- a/src/nfc/doc/snippets/foorecord.cpp
+++ b/src/nfc/doc/snippets/foorecord.cpp
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/snippets/foorecord.h b/src/nfc/doc/snippets/foorecord.h
index e8c130e4..c2501287 100644
--- a/src/nfc/doc/snippets/foorecord.h
+++ b/src/nfc/doc/snippets/foorecord.h
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/snippets/main.cpp b/src/nfc/doc/snippets/main.cpp
index 09d07b02..6f2bb0d7 100644
--- a/src/nfc/doc/snippets/main.cpp
+++ b/src/nfc/doc/snippets/main.cpp
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/snippets/nfc.cpp b/src/nfc/doc/snippets/nfc.cpp
index eb7ef989..82297682 100644
--- a/src/nfc/doc/snippets/nfc.cpp
+++ b/src/nfc/doc/snippets/nfc.cpp
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/src/nfc/doc/src/nfc-index.qdoc b/src/nfc/doc/src/nfc-index.qdoc
index c9acc92b..21f775a6 100644
--- a/src/nfc/doc/src/nfc-index.qdoc
+++ b/src/nfc/doc/src/nfc-index.qdoc
@@ -60,6 +60,15 @@ import statement in your \c .qml file:
\snippet doc_src_qtnfc.qml import
+\section1 Licenses
+
+Qt NFC is available under commercial licenses from \l{The Qt Company}.
+In addition, it is available under free software licenses. Since Qt 5.4,
+these free software licenses are
+\l{GNU Lesser General Public License, version 3}, or
+the \l{GNU General Public License, version 2}.
+See \l{Qt Licensing} for further details.
+
\section1 Related Information
\section2 Guides
diff --git a/src/nfc/doc/src/nfc-qml.qdoc b/src/nfc/doc/src/nfc-qml.qdoc
index 48df6d32..bbacb2de 100644
--- a/src/nfc/doc/src/nfc-qml.qdoc
+++ b/src/nfc/doc/src/nfc-qml.qdoc
@@ -28,7 +28,7 @@
/*!
-\qmlmodule QtNfc 5.2
+\qmlmodule QtNfc 5.11
\title Qt NFC QML Types
\ingroup qmlmodules
\brief Provides QML types for accessing NFC Forum Tags.
diff --git a/src/nfc/neard/neard_helper.cpp b/src/nfc/neard/neard_helper.cpp
index ef0447a0..9922c1a8 100644
--- a/src/nfc/neard/neard_helper.cpp
+++ b/src/nfc/neard/neard_helper.cpp
@@ -62,10 +62,10 @@ NeardHelper::NeardHelper(QObject *parent) :
return;
}
- connect(m_dbusObjectManager, SIGNAL(InterfacesAdded(QDBusObjectPath,InterfaceList)),
- this, SLOT(interfacesAdded(QDBusObjectPath,InterfaceList)));
- connect(m_dbusObjectManager, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)),
- this, SLOT(interfacesRemoved(QDBusObjectPath,QStringList)));
+ connect(m_dbusObjectManager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded,
+ this, &NeardHelper::interfacesAdded);
+ connect(m_dbusObjectManager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
+ this, &NeardHelper::interfacesRemoved);
}
NeardHelper *NeardHelper::instance()
diff --git a/src/nfc/qllcpsocket_android_p.cpp b/src/nfc/qllcpsocket_android_p.cpp
index e29634d4..26b50c34 100644
--- a/src/nfc/qllcpsocket_android_p.cpp
+++ b/src/nfc/qllcpsocket_android_p.cpp
@@ -71,7 +71,7 @@ void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QStrin
QNXNFCManager::instance()->registerLLCPConnection(m_conListener, this);
qQNXNFCDebug() << "Connecting client socket" << serviceUri << m_conListener;
- connect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService()));*/
+ connect(QNXNFCManager::instance(), &QNXNFCManager::llcpDisconnected, this, &QLlcpSocketPrivate::disconnectFromService);*/
}
void QLlcpSocketPrivate::disconnectFromService()
@@ -83,7 +83,7 @@ void QLlcpSocketPrivate::disconnectFromService()
qWarning() << Q_FUNC_INFO << "Error when trying to close LLCP socket";
}
QNXNFCManager::instance()->unregisterLLCPConnection(m_conListener);
- disconnect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService()));
+ disconnect(QNXNFCManager::instance(), &QNXNFCManager::llcpDisconnected, this, &QLlcpSocketPrivate::disconnectFromService);
q->disconnected();
m_conListener = 0;
@@ -96,7 +96,7 @@ bool QLlcpSocketPrivate::bind(quint8 port)
/*m_state = QLlcpSocket::ConnectedState;
m_server = true;
- connect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService()));
+ connect(QNXNFCManager::instance(), &QNXNFCManager::llcpDisconnected, this, &QLlcpSocketPrivate::disconnectFromService);
connected(QNXNFCManager::instance()->getLastTarget());*/
return true;
diff --git a/src/nfc/qndefnfcsmartposterrecord.cpp b/src/nfc/qndefnfcsmartposterrecord.cpp
index 73f2cd21..bc7acfab 100644
--- a/src/nfc/qndefnfcsmartposterrecord.cpp
+++ b/src/nfc/qndefnfcsmartposterrecord.cpp
@@ -566,7 +566,7 @@ void QNdefNfcSmartPosterRecord::addIcon(const QByteArray &type, const QByteArray
rec.setType(type);
rec.setData(data);
- return addIcon(rec);
+ addIcon(rec);
}
/*!
diff --git a/src/nfc/qndefnfctextrecord.cpp b/src/nfc/qndefnfctextrecord.cpp
index 78736cc0..95fb4c66 100644
--- a/src/nfc/qndefnfctextrecord.cpp
+++ b/src/nfc/qndefnfctextrecord.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QNdefNfcTextRecord
- \brief The QNdefNfcTextRecord class provides an NFC RTD-Text
+ \brief The QNdefNfcTextRecord class provides an NFC RTD-Text.
\ingroup connectivity-nfc
\inmodule QtNfc
diff --git a/src/nfc/qndefnfcurirecord.cpp b/src/nfc/qndefnfcurirecord.cpp
index 44b17adf..3438d9f2 100644
--- a/src/nfc/qndefnfcurirecord.cpp
+++ b/src/nfc/qndefnfcurirecord.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QNdefNfcUriRecord
- \brief The QNdefNfcUriRecord class provides an NFC RTD-URI
+ \brief The QNdefNfcUriRecord class provides an NFC RTD-URI.
\ingroup connectivity-nfc
\inmodule QtNfc
diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp
index 099a070c..02e4d918 100644
--- a/src/nfc/qnearfieldmanager.cpp
+++ b/src/nfc/qnearfieldmanager.cpp
@@ -119,6 +119,19 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QNearFieldManager::AdapterState
+
+ \since 5.12
+
+ This enum describes the different states a NFC adapter can have.
+
+ \value Offline The nfc adapter is offline.
+ \value TurningOn The nfc adapter is turning on.
+ \value Online The nfc adapter is online.
+ \value TurningOff The nfc adapter is turning off.
+*/
+
+/*!
\enum QNearFieldManager::TargetAccessMode
This enum describes the different access modes an application can have.
@@ -133,6 +146,16 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn void QNearFieldManager::adapterStateChanged(AdapterState state)
+
+ \since 5.12
+
+ This signal is emitted whenever the state of the NFC adapter changed.
+
+ \note Currently, this signal is only emitted on Android.
+*/
+
+/*!
\fn void QNearFieldManager::targetDetected(QNearFieldTarget *target)
This signal is emitted whenever a target is detected. The \a target parameter represents the
@@ -169,10 +192,14 @@ QT_BEGIN_NAMESPACE
QNearFieldManager::QNearFieldManager(QObject *parent)
: QObject(parent), d_ptr(new QNearFieldManagerPrivateImpl)
{
- connect(d_ptr, SIGNAL(targetDetected(QNearFieldTarget*)),
- this, SIGNAL(targetDetected(QNearFieldTarget*)));
- connect(d_ptr, SIGNAL(targetLost(QNearFieldTarget*)),
- this, SIGNAL(targetLost(QNearFieldTarget*)));
+ qRegisterMetaType<AdapterState>();
+
+ connect(d_ptr, &QNearFieldManagerPrivate::adapterStateChanged,
+ this, &QNearFieldManager::adapterStateChanged);
+ connect(d_ptr, &QNearFieldManagerPrivate::targetDetected,
+ this, &QNearFieldManager::targetDetected);
+ connect(d_ptr, &QNearFieldManagerPrivate::targetLost,
+ this, &QNearFieldManager::targetLost);
}
/*!
@@ -186,10 +213,14 @@ QNearFieldManager::QNearFieldManager(QObject *parent)
QNearFieldManager::QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent)
: QObject(parent), d_ptr(backend)
{
- connect(d_ptr, SIGNAL(targetDetected(QNearFieldTarget*)),
- this, SIGNAL(targetDetected(QNearFieldTarget*)));
- connect(d_ptr, SIGNAL(targetLost(QNearFieldTarget*)),
- this, SIGNAL(targetLost(QNearFieldTarget*)));
+ qRegisterMetaType<AdapterState>();
+
+ connect(d_ptr, &QNearFieldManagerPrivate::adapterStateChanged,
+ this, &QNearFieldManager::adapterStateChanged);
+ connect(d_ptr, &QNearFieldManagerPrivate::targetDetected,
+ this, &QNearFieldManager::targetDetected);
+ connect(d_ptr, &QNearFieldManagerPrivate::targetLost,
+ this, &QNearFieldManager::targetLost);
}
/*!
@@ -201,7 +232,10 @@ QNearFieldManager::~QNearFieldManager()
}
/*!
- Returns true if NFC functionality is available; otherwise returns false.
+ Returns \c true if the device has a NFC adapter and
+ it is turned on; otherwise returns \c false.
+
+ \sa isSupported()
*/
bool QNearFieldManager::isAvailable() const
{
@@ -211,6 +245,19 @@ bool QNearFieldManager::isAvailable() const
}
/*!
+ \since 5.12
+
+ Returns \c true if the underlying device has a NFC adapter; otherwise returns \c false.
+
+ \sa isAvailable()
+*/
+bool QNearFieldManager::isSupported() const
+{
+ Q_D(const QNearFieldManager);
+
+ return d->isSupported();
+}
+/*!
\fn bool QNearFieldManager::startTargetDetection()
Starts detecting targets and returns true if target detection is
diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h
index 9583e01f..500b9631 100644
--- a/src/nfc/qnearfieldmanager.h
+++ b/src/nfc/qnearfieldmanager.h
@@ -56,6 +56,13 @@ class Q_NFC_EXPORT QNearFieldManager : public QObject
Q_DECLARE_PRIVATE(QNearFieldManager)
public:
+ enum class AdapterState {
+ Offline = 1,
+ TurningOn = 2,
+ Online = 3,
+ TurningOff = 4
+ };
+ Q_ENUM(AdapterState)
enum TargetAccessMode {
NoTargetAccess = 0x00,
NdefReadTargetAccess = 0x01,
@@ -70,6 +77,7 @@ public:
~QNearFieldManager();
bool isAvailable() const;
+ bool isSupported() const;
void setTargetAccessModes(TargetAccessModes accessModes);
TargetAccessModes targetAccessModes() const;
@@ -91,6 +99,7 @@ public:
bool unregisterNdefMessageHandler(int handlerId);
Q_SIGNALS:
+ void adapterStateChanged(AdapterState state);
void targetDetected(QNearFieldTarget *target);
void targetLost(QNearFieldTarget *target);
diff --git a/src/nfc/qnearfieldmanager_android.cpp b/src/nfc/qnearfieldmanager_android.cpp
index a5693218..297f8ef8 100644
--- a/src/nfc/qnearfieldmanager_android.cpp
+++ b/src/nfc/qnearfieldmanager_android.cpp
@@ -48,22 +48,52 @@
#include "qdebug.h"
#include "qlist.h"
+#include <QScopedPointer>
#include <QtCore/QMetaType>
#include <QtCore/QMetaMethod>
+#include <QtCore/private/qjnihelpers_p.h>
QT_BEGIN_NAMESPACE
+Q_GLOBAL_STATIC(QAndroidJniObject, broadcastReceiver)
+Q_GLOBAL_STATIC(QList<QNearFieldManagerPrivateImpl *>, broadcastListener)
+
+extern "C"
+{
+ JNIEXPORT void JNICALL Java_org_qtproject_qt5_android_nfc_QtNfcBroadcastReceiver_jniOnReceive(
+ JNIEnv */*env*/, jobject /*javaObject*/, jint state)
+ {
+ QNearFieldManager::AdapterState adapterState = static_cast<QNearFieldManager::AdapterState>((int) state);
+
+ for (const auto listener : *broadcastListener) {
+ Q_EMIT listener->adapterStateChanged(adapterState);
+ }
+ }
+}
+
QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() :
m_detecting(false), m_handlerID(0)
{
qRegisterMetaType<QAndroidJniObject>("QAndroidJniObject");
qRegisterMetaType<QNdefMessage>("QNdefMessage");
- connect(this, SIGNAL(targetDetected(QNearFieldTarget*)), this, SLOT(handlerTargetDetected(QNearFieldTarget*)));
- connect(this, SIGNAL(targetLost(QNearFieldTarget*)), this, SLOT(handlerTargetLost(QNearFieldTarget*)));
+
+ if (!broadcastReceiver->isValid()) {
+ *broadcastReceiver = QAndroidJniObject("org/qtproject/qt5/android/nfc/QtNfcBroadcastReceiver",
+ "(Landroid/content/Context;)V", QtAndroidPrivate::context());
+ }
+ broadcastListener->append(this);
+
+ connect(this, &QNearFieldManagerPrivateImpl::targetDetected, this, &QNearFieldManagerPrivateImpl::handlerTargetDetected);
+ connect(this, &QNearFieldManagerPrivateImpl::targetLost, this, &QNearFieldManagerPrivateImpl::handlerTargetLost);
}
QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
{
+ broadcastListener->removeOne(this);
+ if (broadcastListener->isEmpty()) {
+ broadcastReceiver->callMethod<void>("unregisterReceiver");
+ *broadcastReceiver = QAndroidJniObject();
+ }
}
void QNearFieldManagerPrivateImpl::handlerTargetDetected(QNearFieldTarget *target)
@@ -71,12 +101,12 @@ void QNearFieldManagerPrivateImpl::handlerTargetDetected(QNearFieldTarget *targe
if (ndefMessageHandlers.count() == 0 && ndefFilterHandlers.count() == 0) // if no handler is registered
return;
if (target->hasNdefMessage()) {
- connect(target, SIGNAL(ndefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerNdefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)));
- connect(target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerRequestCompleted(const QNearFieldTarget::RequestId &)));
- connect(target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerError(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)));
+ connect(reinterpret_cast<NearFieldTarget *>(target), &NearFieldTarget::ndefMessageRead,
+ this, &QNearFieldManagerPrivateImpl::handlerNdefMessageRead);
+ connect(target, &QNearFieldTarget::requestCompleted,
+ this, &QNearFieldManagerPrivateImpl::handlerRequestCompleted);
+ connect(target, &QNearFieldTarget::error,
+ this, &QNearFieldManagerPrivateImpl::handlerError);
QNearFieldTarget::RequestId id = target->readNdefMessages();
m_idToTarget.insert(id, target);
@@ -85,12 +115,12 @@ void QNearFieldManagerPrivateImpl::handlerTargetDetected(QNearFieldTarget *targe
void QNearFieldManagerPrivateImpl::handlerTargetLost(QNearFieldTarget *target)
{
- disconnect(target, SIGNAL(ndefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerNdefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)));
- disconnect(target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerRequestCompleted(const QNearFieldTarget::RequestId &)));
- disconnect(target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)),
- this, SLOT(handlerError(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)));
+ disconnect(reinterpret_cast<NearFieldTarget *>(target), &NearFieldTarget::ndefMessageRead,
+ this, &QNearFieldManagerPrivateImpl::handlerNdefMessageRead);
+ disconnect(target, &QNearFieldTarget::requestCompleted,
+ this, &QNearFieldManagerPrivateImpl::handlerRequestCompleted);
+ disconnect(target, &QNearFieldTarget::error,
+ this, &QNearFieldManagerPrivateImpl::handlerError);
m_idToTarget.remove(m_idToTarget.key(target));
}
@@ -176,6 +206,11 @@ bool QNearFieldManagerPrivateImpl::isAvailable() const
return AndroidNfc::isAvailable();
}
+bool QNearFieldManagerPrivateImpl::isSupported() const
+{
+ return AndroidNfc::isSupported();
+}
+
bool QNearFieldManagerPrivateImpl::startTargetDetection()
{
if (m_detecting)
@@ -282,8 +317,8 @@ void QNearFieldManagerPrivateImpl::onTargetDiscovered(QAndroidJniObject intent)
target->setIntent(intent); // Updating existing target
} else {
target = new NearFieldTarget(intent, uid, this);
- connect(target, SIGNAL(targetDestroyed(QByteArray)), this, SLOT(onTargetDestroyed(QByteArray)));
- connect(target, SIGNAL(targetLost(QNearFieldTarget*)), this, SIGNAL(targetLost(QNearFieldTarget*)));
+ connect(target, &NearFieldTarget::targetDestroyed, this, &QNearFieldManagerPrivateImpl::onTargetDestroyed);
+ connect(target, &NearFieldTarget::targetLost, this, &QNearFieldManagerPrivateImpl::targetLost);
}
emit targetDetected(target);
}
diff --git a/src/nfc/qnearfieldmanager_android_p.h b/src/nfc/qnearfieldmanager_android_p.h
index 69c99709..563d26bc 100644
--- a/src/nfc/qnearfieldmanager_android_p.h
+++ b/src/nfc/qnearfieldmanager_android_p.h
@@ -76,6 +76,7 @@ public:
~QNearFieldManagerPrivateImpl();
virtual bool isAvailable() const;
+ bool isSupported() const override;
virtual bool startTargetDetection();
virtual void stopTargetDetection();
virtual int registerNdefMessageHandler(QObject *object, const QMetaMethod &method);
diff --git a/src/nfc/qnearfieldmanager_emulator.cpp b/src/nfc/qnearfieldmanager_emulator.cpp
index 3186bae5..c2c037f6 100644
--- a/src/nfc/qnearfieldmanager_emulator.cpp
+++ b/src/nfc/qnearfieldmanager_emulator.cpp
@@ -53,8 +53,8 @@ QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
tagActivator->initialize();
- connect(tagActivator, SIGNAL(tagActivated(TagBase*)), this, SLOT(tagActivated(TagBase*)));
- connect(tagActivator, SIGNAL(tagDeactivated(TagBase*)), this, SLOT(tagDeactivated(TagBase*)));
+ connect(tagActivator, &TagActivator::tagActivated, this, &QNearFieldManagerPrivateImpl::tagActivated);
+ connect(tagActivator, &TagActivator::tagDeactivated, this, &QNearFieldManagerPrivateImpl::tagDeactivated);
}
QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
diff --git a/src/nfc/qnearfieldmanager_neard.cpp b/src/nfc/qnearfieldmanager_neard.cpp
index f1758ae9..7c1c6e05 100644
--- a/src/nfc/qnearfieldmanager_neard.cpp
+++ b/src/nfc/qnearfieldmanager_neard.cpp
@@ -80,10 +80,10 @@ QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
if (!found) {
qCWarning(QT_NFC_NEARD) << "no adapter found, neard daemon running?";
} else {
- connect(m_neardHelper, SIGNAL(tagFound(QDBusObjectPath)),
- this, SLOT(handleTagFound(QDBusObjectPath)));
- connect(m_neardHelper, SIGNAL(tagRemoved(QDBusObjectPath)),
- this, SLOT(handleTagRemoved(QDBusObjectPath)));
+ connect(m_neardHelper, &NeardHelper::tagFound,
+ this, &QNearFieldManagerPrivateImpl::handleTagFound);
+ connect(m_neardHelper, &NeardHelper::tagRemoved,
+ this, &QNearFieldManagerPrivateImpl::handleTagRemoved);
}
}
@@ -114,6 +114,21 @@ bool QNearFieldManagerPrivateImpl::isAvailable() const
return false;
}
+bool QNearFieldManagerPrivateImpl::isSupported() const
+{
+ if (m_adapterPath.isEmpty()) {
+ qCWarning(QT_NFC_NEARD) << "no adapter found, neard daemon running?";
+ return false;
+ }
+
+ if (!m_neardHelper->dbusObjectManager()->isValid() || m_adapterPath.isNull()) {
+ qCWarning(QT_NFC_NEARD) << "dbus object manager invalid or adapter path invalid";
+ return false;
+ }
+
+ return true;
+}
+
bool QNearFieldManagerPrivateImpl::startTargetDetection()
{
qCDebug(QT_NFC_NEARD) << "starting target detection";
diff --git a/src/nfc/qnearfieldmanager_neard_p.h b/src/nfc/qnearfieldmanager_neard_p.h
index b50f947a..cf026982 100644
--- a/src/nfc/qnearfieldmanager_neard_p.h
+++ b/src/nfc/qnearfieldmanager_neard_p.h
@@ -75,6 +75,8 @@ public:
bool isAvailable() const;
+ bool isSupported() const override;
+
bool startTargetDetection();
void stopTargetDetection();
diff --git a/src/nfc/qnearfieldmanager_p.h b/src/nfc/qnearfieldmanager_p.h
index 7e461da8..351c844a 100644
--- a/src/nfc/qnearfieldmanager_p.h
+++ b/src/nfc/qnearfieldmanager_p.h
@@ -82,6 +82,11 @@ public:
return false;
}
+ virtual bool isSupported() const
+ {
+ return false;
+ }
+
virtual bool startTargetDetection()
{
return false;
@@ -124,6 +129,7 @@ public:
}
signals:
+ void adapterStateChanged(QNearFieldManager::AdapterState state);
void targetDetected(QNearFieldTarget *target);
void targetLost(QNearFieldTarget *target);
diff --git a/src/nfc/qnearfieldsharemanager.cpp b/src/nfc/qnearfieldsharemanager.cpp
index 515a9d62..0709f60e 100644
--- a/src/nfc/qnearfieldsharemanager.cpp
+++ b/src/nfc/qnearfieldsharemanager.cpp
@@ -149,7 +149,7 @@ QNearFieldShareManager::~QNearFieldShareManager()
void QNearFieldShareManager::setShareModes(ShareModes mode)
{
Q_D(QNearFieldShareManager);
- return d->setShareModes(mode);
+ d->setShareModes(mode);
}
/*!
diff --git a/src/nfc/qnearfieldtagtype1.cpp b/src/nfc/qnearfieldtagtype1.cpp
index 34f2c8b8..7f27fbe9 100644
--- a/src/nfc/qnearfieldtagtype1.cpp
+++ b/src/nfc/qnearfieldtagtype1.cpp
@@ -440,9 +440,7 @@ QNearFieldTarget::RequestId QNearFieldTagType1::readNdefMessages()
if (d->m_readNdefMessageState == QNearFieldTagType1Private::NotReadingNdefMessage) {
d->progressToNextNdefReadMessageState();
} else {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, NdefReadError),
- Q_ARG(QNearFieldTarget::RequestId, d->m_readNdefRequestId));
+ reportError(QNearFieldTarget::NdefReadError, d->m_readNdefRequestId);
}
return d->m_readNdefRequestId;
@@ -462,9 +460,7 @@ QNearFieldTarget::RequestId QNearFieldTagType1::writeNdefMessages(const QList<QN
d->m_ndefWriteMessages = messages;
d->progressToNextNdefWriteMessageState();
} else {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, NdefWriteError),
- Q_ARG(QNearFieldTarget::RequestId, d->m_readNdefRequestId));
+ reportError(QNearFieldTarget::NdefWriteError, d->m_readNdefRequestId);
}
return d->m_writeNdefRequestId;
diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp
index e642824b..e9a6fa11 100644
--- a/src/nfc/qnearfieldtarget.cpp
+++ b/src/nfc/qnearfieldtarget.cpp
@@ -530,4 +530,17 @@ bool QNearFieldTarget::handleResponse(const QNearFieldTarget::RequestId &id,
return true;
}
+/*!
+ \since 5.12
+
+ Reports the \a error for the request \a id by appending the signal emission to the event queue.
+*/
+void QNearFieldTarget::reportError(QNearFieldTarget::Error error,
+ const QNearFieldTarget::RequestId &id)
+{
+ QMetaObject::invokeMethod(this, [this, error, id]() {
+ Q_EMIT this->error(error, id);
+ }, Qt::QueuedConnection);
+}
+
QT_END_NAMESPACE
diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h
index e51960f7..868b52d5 100644
--- a/src/nfc/qnearfieldtarget.h
+++ b/src/nfc/qnearfieldtarget.h
@@ -153,6 +153,8 @@ protected:
Q_INVOKABLE virtual bool handleResponse(const QNearFieldTarget::RequestId &id,
const QByteArray &response);
+ void reportError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id);
+
Q_SIGNALS:
void disconnected();
diff --git a/src/nfc/qnearfieldtarget_android.cpp b/src/nfc/qnearfieldtarget_android.cpp
index 50c5c1b3..78da6ac2 100644
--- a/src/nfc/qnearfieldtarget_android.cpp
+++ b/src/nfc/qnearfieldtarget_android.cpp
@@ -147,25 +147,19 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages()
// Making sure that target is still in range
QNearFieldTarget::RequestId requestId(new QNearFieldTarget::RequestIdPrivate);
if (!m_intent.isValid()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, requestId);
return requestId;
}
// Getting Ndef technology object
if (!setTagTechnology({NDEFTECHNOLOGY})) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnsupportedError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::UnsupportedError, requestId);
return requestId;
}
// Connect
if (!connect()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, requestId);
return requestId;
}
@@ -174,9 +168,7 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages()
if (catchJavaExceptions())
ndefMessage = QAndroidJniObject();
if (!ndefMessage.isValid()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefReadError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::NdefReadError, requestId);
return requestId;
}
@@ -191,13 +183,17 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages()
// Sending QNdefMessage, requestCompleted and exit.
QNdefMessage qNdefMessage = QNdefMessage::fromByteArray(ndefMessageQBA);
- QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection,
- Q_ARG(const QNdefMessage&, qNdefMessage));
- QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
- QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection,
- Q_ARG(const QNdefMessage&, qNdefMessage),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ QMetaObject::invokeMethod(this, [this, qNdefMessage]() {
+ Q_EMIT this->QNearFieldTarget::ndefMessageRead(qNdefMessage);
+ }, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, [this, requestId]() {
+ Q_EMIT this->requestCompleted(requestId);
+ }, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, [this, qNdefMessage, requestId]() {
+ //TODO This is an Android specific signal in NearFieldTarget.
+ // We need to check if it is still necessary.
+ Q_EMIT this->ndefMessageRead(qNdefMessage, requestId);
+ }, Qt::QueuedConnection);
return requestId;
}
@@ -245,9 +241,7 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma
// Connecting
QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate());
if (!connect()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, requestId);
return requestId;
}
@@ -259,9 +253,7 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma
// Writing
QAndroidJniObject myNewVal = m_tagTech.callObjectMethod("transceive", "([B)[B", jba);
if (catchJavaExceptions()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::CommandError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::CommandError, requestId);
return requestId;
}
QByteArray result = jbyteArrayToQByteArray(myNewVal.object<jbyteArray>());
@@ -273,8 +265,9 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma
// Closing connection
disconnect(); // IOException at this point does not matter anymore.
}
- QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ QMetaObject::invokeMethod(this, [this, requestId]() {
+ Q_EMIT this->requestCompleted(requestId);
+ }, Qt::QueuedConnection);
return requestId;
}
@@ -297,7 +290,6 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef
QAndroidJniEnvironment env;
const char *writeMethod;
- QAndroidJniObject tagTechnology;
if (!setTagTechnology({NDEFFORMATABLETECHNOLOGY, NDEFTECHNOLOGY}))
return QNearFieldTarget::RequestId();
@@ -311,9 +303,7 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef
// Connecting
QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate());
if (!connect()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, requestId);
return requestId;
}
@@ -324,18 +314,14 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef
env->SetByteArrayRegion(jba.object<jbyteArray>(), 0, ba.size(), reinterpret_cast<jbyte*>(ba.data()));
QAndroidJniObject jmessage = QAndroidJniObject("android/nfc/NdefMessage", "([B)V", jba.object<jbyteArray>());
if (catchJavaExceptions()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::UnknownError, requestId);
return requestId;
}
// Writing
- tagTechnology.callMethod<void>(writeMethod, "(Landroid/nfc/NdefMessage;)V", jmessage.object<jobject>());
+ m_tagTech.callMethod<void>(writeMethod, "(Landroid/nfc/NdefMessage;)V", jmessage.object<jobject>());
if (catchJavaExceptions()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefWriteError),
- Q_ARG(const QNearFieldTarget::RequestId&, requestId));
+ reportError(QNearFieldTarget::NdefWriteError, requestId);
return requestId;
}
diff --git a/src/nfc/qnearfieldtarget_emulator.cpp b/src/nfc/qnearfieldtarget_emulator.cpp
index 29b1f74d..030718cc 100644
--- a/src/nfc/qnearfieldtarget_emulator.cpp
+++ b/src/nfc/qnearfieldtarget_emulator.cpp
@@ -82,9 +82,7 @@ QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command)
// tag not in proximity
if (!tagMap.value(m_tag)) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, TargetOutOfRangeError),
- Q_ARG(QNearFieldTarget::RequestId, id));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, id);
return id;
}
@@ -93,17 +91,13 @@ QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command)
QByteArray response = m_tag->processCommand(command + char(crc & 0xff) + char(crc >> 8));
if (response.isEmpty()) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, NoResponseError),
- Q_ARG(QNearFieldTarget::RequestId, id));
+ reportError(QNearFieldTarget::NoResponseError, id);
return id;
}
// check crc
if (qChecksum(response.constData(), response.length(), Qt::ChecksumItuV41) != 0) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError),
- Q_ARG(QNearFieldTarget::RequestId, id));
+ reportError(QNearFieldTarget::ChecksumMismatchError, id);
return id;
}
@@ -152,9 +146,7 @@ QNearFieldTarget::RequestId TagType2::sendCommand(const QByteArray &command)
// tag not in proximity
if (!tagMap.value(m_tag)) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, TargetOutOfRangeError),
- Q_ARG(QNearFieldTarget::RequestId, id));
+ reportError(QNearFieldTarget::TargetOutOfRangeError, id);
return id;
}
@@ -168,9 +160,7 @@ QNearFieldTarget::RequestId TagType2::sendCommand(const QByteArray &command)
if (response.length() > 1) {
// check crc
if (qChecksum(response.constData(), response.length(), Qt::ChecksumItuV41) != 0) {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError),
- Q_ARG(QNearFieldTarget::RequestId, id));
+ reportError(QNearFieldTarget::ChecksumMismatchError, id);
return id;
}
diff --git a/src/nfc/qnearfieldtarget_neard_p.h b/src/nfc/qnearfieldtarget_neard_p.h
index c84e033f..625cee67 100644
--- a/src/nfc/qnearfieldtarget_neard_p.h
+++ b/src/nfc/qnearfieldtarget_neard_p.h
@@ -353,14 +353,13 @@ private:
if (!newNdefMessage.isEmpty()) {
QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection,
- Q_ARG(const QNdefMessage, newNdefMessage));
+ Q_ARG(QNdefMessage, newNdefMessage));
// the request id in requestCompleted has to match the one created in readNdefMessages
- QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId));
+ QMetaObject::invokeMethod(this, [this]() {
+ Q_EMIT this->requestCompleted(this->m_currentReadRequestId);
+ }, Qt::QueuedConnection);
} else {
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError),
- Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId));
+ this->reportError(QNearFieldTarget::UnknownError, m_currentReadRequestId);
}
m_readRequested = false;
@@ -388,14 +387,13 @@ private:
reply.waitForFinished();
if (reply.isError()) {
qCWarning(QT_NFC_NEARD) << "Error writing to NFC tag" << reply.error();
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError),
- Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId));
+ this->reportError(QNearFieldTarget::UnknownError, m_currentWriteRequestId);
}
QMetaObject::invokeMethod(this, "ndefMessagesWritten", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
- Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId));
+ QMetaObject::invokeMethod(this, [this]() {
+ Q_EMIT this->requestCompleted(this->m_currentWriteRequestId);
+ }, Qt::QueuedConnection);
}
// invalidate current write request
diff --git a/src/nfc/qqmlndefrecord.cpp b/src/nfc/qqmlndefrecord.cpp
index cd6620cc..a7304f00 100644
--- a/src/nfc/qqmlndefrecord.cpp
+++ b/src/nfc/qqmlndefrecord.cpp
@@ -228,7 +228,7 @@ QQmlNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record
continue;
return static_cast<QQmlNdefRecord *>(metaObject->newInstance(
- Q_ARG(QNdefRecord, record), Q_ARG(QObject *, 0)));
+ Q_ARG(QNdefRecord, record), Q_ARG(QObject*, 0)));
}
return new QQmlNdefRecord(record);