summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2017-10-17 13:04:45 +0200
committerAlex Blasche <alexander.blasche@qt.io>2017-10-17 13:55:46 +0200
commitd6c4d74f4f32699a013705d492ee467ec5006df1 (patch)
tree9ffeaaa124986049fd5b6a992f61b26b35badd10 /src
parente26edb020084554e8b567d3bc15ce638394cf7fc (diff)
parent125cdccc346903d6e70ed26289cdaed85e26ec3f (diff)
Merge remote-tracking branch 'gerrit/dev' into win
Diffstat (limited to 'src')
-rw-r--r--src/android/bluetooth/bluetooth.pri17
-rw-r--r--src/android/bluetooth/bluetooth.pro21
-rw-r--r--src/android/bluetooth/bundledjar.pro3
-rw-r--r--src/android/bluetooth/distributedjar.pro2
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java171
-rw-r--r--src/android/nfc/bundledjar.pro3
-rw-r--r--src/android/nfc/distributedjar.pro2
-rw-r--r--src/android/nfc/nfc.pri12
-rw-r--r--src/android/nfc/nfc.pro15
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp30
-rw-r--r--src/bluetooth/android/inputstreamthread.cpp6
-rw-r--r--src/bluetooth/android/inputstreamthread_p.h1
-rw-r--r--src/bluetooth/android/jni_android.cpp2
-rw-r--r--src/bluetooth/android/lowenergynotificationhub.cpp5
-rw-r--r--src/bluetooth/bluetooth.pro28
-rw-r--r--src/bluetooth/bluez/adapter1_bluez5.cpp4
-rw-r--r--src/bluetooth/bluez/adapter1_bluez5_p.h23
-rw-r--r--src/bluetooth/bluez/bluetoothmanagement.cpp314
-rw-r--r--src/bluetooth/bluez/bluetoothmanagement_p.h98
-rw-r--r--src/bluetooth/bluez/bluez.pri8
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp1
-rw-r--r--src/bluetooth/bluez/bluez5_helper_p.h2
-rw-r--r--src/bluetooth/bluez/bluez_data_p.h11
-rw-r--r--src/bluetooth/bluez/device1_bluez5.cpp3
-rw-r--r--src/bluetooth/bluez/device1_bluez5_p.h38
-rwxr-xr-xsrc/bluetooth/bluez/generate14
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp44
-rw-r--r--src/bluetooth/bluez/hcimanager_p.h4
-rw-r--r--src/bluetooth/bluez/objectmanager_p.h4
-rw-r--r--src/bluetooth/bluez/org.bluez.Adapter1.xml4
-rw-r--r--src/bluetooth/bluez/org.bluez.Device1.xml10
-rw-r--r--src/bluetooth/bluez/remotedevicemanager.cpp170
-rw-r--r--src/bluetooth/bluez/remotedevicemanager_p.h99
-rw-r--r--src/bluetooth/configure.json13
-rw-r--r--src/bluetooth/doc/qtbluetooth.qdocconf1
-rw-r--r--src/bluetooth/doc/src/bluetooth-cpp.qdoc10
-rw-r--r--src/bluetooth/doc/src/bluetooth-index.qdoc10
-rw-r--r--src/bluetooth/doc/src/bluetooth-le-overview.qdoc10
-rw-r--r--src/bluetooth/doc/src/bluetooth-overview.qdoc10
-rw-r--r--src/bluetooth/doc/src/bluetooth-qml.qdoc10
-rw-r--r--src/bluetooth/doc/src/examples.qdoc10
-rw-r--r--src/bluetooth/osx/osxbluetooth_p.h41
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm17
-rw-r--r--src/bluetooth/osx/osxbtl2capchannel.mm4
-rw-r--r--src/bluetooth/osx/osxbtledeviceinquiry.mm9
-rw-r--r--src/bluetooth/osx/osxbtobexsession.mm22
-rw-r--r--src/bluetooth/osx/osxbtperipheralmanager.mm4
-rw-r--r--src/bluetooth/osx/osxbtrfcommchannel.mm4
-rw-r--r--src/bluetooth/osx/osxbtutility.mm15
-rw-r--r--src/bluetooth/osx/osxbtutility_p.h32
-rw-r--r--src/bluetooth/qbluetooth.h2
-rw-r--r--src/bluetooth/qbluetoothaddress.h2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.cpp18
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.h6
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp7
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp71
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm14
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h7
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp43
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.h5
-rw-r--r--src/bluetooth/qbluetoothhostinfo.h2
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.h6
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp8
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_osx.mm18
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.h2
-rw-r--r--src/bluetooth/qbluetoothserver.h4
-rw-r--r--src/bluetooth/qbluetoothserver_osx.mm10
-rw-r--r--src/bluetooth/qbluetoothserver_osx_p.h4
-rw-r--r--src/bluetooth/qbluetoothserver_winrt.cpp14
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.cpp10
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.h6
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp4
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_osx.mm16
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_p.h8
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp3
-rw-r--r--src/bluetooth/qbluetoothserviceinfo.cpp2
-rw-r--r--src/bluetooth/qbluetoothserviceinfo.h2
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_osx.mm4
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_winrt.cpp3
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp12
-rw-r--r--src/bluetooth/qbluetoothsocket.h7
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp137
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp14
-rw-r--r--src/bluetooth/qbluetoothsocket_osx.mm16
-rw-r--r--src/bluetooth/qbluetoothsocket_osx_p.h12
-rw-r--r--src/bluetooth/qbluetoothsocket_p.cpp10
-rw-r--r--src/bluetooth/qbluetoothsocket_p.h25
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt.cpp33
-rw-r--r--src/bluetooth/qbluetoothtransfermanager.h4
-rw-r--r--src/bluetooth/qbluetoothtransferreply.h2
-rw-r--r--src/bluetooth/qbluetoothtransferreply_osx.mm14
-rw-r--r--src/bluetooth/qbluetoothtransferreply_osx_p.h8
-rw-r--r--src/bluetooth/qbluetoothtransferrequest.h2
-rw-r--r--src/bluetooth/qbluetoothtransferrequest_p.h2
-rw-r--r--src/bluetooth/qbluetoothutils_win.cpp94
-rw-r--r--src/bluetooth/qbluetoothuuid.h6
-rw-r--r--src/bluetooth/qleadvertiser_bluez.cpp17
-rw-r--r--src/bluetooth/qleadvertiser_p.h1
-rw-r--r--src/bluetooth/qlowenergyadvertisingdata.h2
-rw-r--r--src/bluetooth/qlowenergyadvertisingparameters.h2
-rw-r--r--src/bluetooth/qlowenergycharacteristic.h2
-rw-r--r--src/bluetooth/qlowenergyconnectionparameters.h2
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp59
-rw-r--r--src/bluetooth/qlowenergycontroller.h9
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp170
-rw-r--r--src/bluetooth/qlowenergycontroller_osx.mm4
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h16
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp8
-rw-r--r--src/bluetooth/qlowenergydescriptor.h2
-rw-r--r--src/bluetooth/qlowenergyservice.cpp10
-rw-r--r--src/bluetooth/qlowenergyservice.h2
-rw-r--r--src/bluetooth/qlowenergyservice_osx.mm10
-rw-r--r--src/bluetooth/qlowenergyservicedata.h2
-rw-r--r--src/bluetooth/qtbluetoothglobal.h (renamed from src/bluetooth/qbluetoothglobal.h)2
-rw-r--r--src/bluetooth/qtbluetoothglobal_p.h59
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h2
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothsocket.cpp5
-rw-r--r--src/imports/bluetooth/qdeclarativebluetoothsocket_p.h1
-rw-r--r--src/nfc/doc/src/examples.qdoc8
-rw-r--r--src/nfc/doc/src/nfc-android.qdoc8
-rw-r--r--src/nfc/doc/src/nfc-cpp.qdoc8
-rw-r--r--src/nfc/doc/src/nfc-index.qdoc10
-rw-r--r--src/nfc/doc/src/nfc-overview.qdoc10
-rw-r--r--src/nfc/doc/src/nfc-qml.qdoc8
-rw-r--r--src/nfc/nfc.pro5
-rw-r--r--src/nfc/qllcpserver_p.h2
-rw-r--r--src/nfc/qllcpserver_p_p.h2
-rw-r--r--src/nfc/qllcpsocket_p.h2
-rw-r--r--src/nfc/qllcpsocket_p_p.h2
-rw-r--r--src/nfc/qndeffilter.h2
-rw-r--r--src/nfc/qndefmessage.h2
-rw-r--r--src/nfc/qndefnfcsmartposterrecord.cpp8
-rw-r--r--src/nfc/qndefnfcsmartposterrecord.h2
-rw-r--r--src/nfc/qndefnfctextrecord.h2
-rw-r--r--src/nfc/qndefnfcurirecord.h2
-rw-r--r--src/nfc/qndefrecord.h2
-rw-r--r--src/nfc/qndefrecord_p.h2
-rw-r--r--src/nfc/qnearfieldmanager.h6
-rw-r--r--src/nfc/qnearfieldmanager_p.h2
-rw-r--r--src/nfc/qnearfieldsharemanager.h4
-rw-r--r--src/nfc/qnearfieldsharetarget.h2
-rw-r--r--src/nfc/qnearfieldtagtype1.cpp4
-rw-r--r--src/nfc/qnearfieldtarget.h4
-rw-r--r--src/nfc/qnearfieldtarget_p.h2
-rw-r--r--src/nfc/qnfc.cpp2
-rw-r--r--src/nfc/qqmlndefrecord.h4
-rw-r--r--src/nfc/qtlv_p.h2
-rw-r--r--src/nfc/qtnfcglobal.h (renamed from src/nfc/qnfcglobal.h)2
-rw-r--r--src/nfc/qtnfcglobal_p.h59
-rw-r--r--src/nfc/targetemulator_p.h2
-rw-r--r--src/tools/sdpscanner/qt_attribution.json12
152 files changed, 2136 insertions, 537 deletions
diff --git a/src/android/bluetooth/bluetooth.pri b/src/android/bluetooth/bluetooth.pri
deleted file mode 100644
index fa811ac1..00000000
--- a/src/android/bluetooth/bluetooth.pri
+++ /dev/null
@@ -1,17 +0,0 @@
-CONFIG += java
-DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
-API_VERSION = android-21
-
-PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth
-
-JAVACLASSPATH += $$PWD/src/
-JAVASOURCES += \
- $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \
- $$PATHPREFIX/QtBluetoothSocketServer.java \
- $$PATHPREFIX/QtBluetoothInputStreamThread.java \
- $$PATHPREFIX/QtBluetoothLE.java \
- $$PATHPREFIX/QtBluetoothLEServer.java
-
-# install
-target.path = $$[QT_INSTALL_PREFIX]/jar
-INSTALLS += target
diff --git a/src/android/bluetooth/bluetooth.pro b/src/android/bluetooth/bluetooth.pro
index 8d19c1b7..b76b392c 100644
--- a/src/android/bluetooth/bluetooth.pro
+++ b/src/android/bluetooth/bluetooth.pro
@@ -1,2 +1,19 @@
-TEMPLATE = subdirs
-SUBDIRS += bundledjar.pro distributedjar.pro
+TARGET = QtAndroidBluetooth
+
+CONFIG += java
+DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
+API_VERSION = android-21
+
+PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth
+
+JAVACLASSPATH += $$PWD/src/
+JAVASOURCES += \
+ $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \
+ $$PATHPREFIX/QtBluetoothSocketServer.java \
+ $$PATHPREFIX/QtBluetoothInputStreamThread.java \
+ $$PATHPREFIX/QtBluetoothLE.java \
+ $$PATHPREFIX/QtBluetoothLEServer.java
+
+# install
+target.path = $$[QT_INSTALL_PREFIX]/jar
+INSTALLS += target
diff --git a/src/android/bluetooth/bundledjar.pro b/src/android/bluetooth/bundledjar.pro
deleted file mode 100644
index 8912674a..00000000
--- a/src/android/bluetooth/bundledjar.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TARGET = QtAndroidBluetooth-bundled
-CONFIG += bundled_jar_file
-include(bluetooth.pri)
diff --git a/src/android/bluetooth/distributedjar.pro b/src/android/bluetooth/distributedjar.pro
deleted file mode 100644
index a155bdf2..00000000
--- a/src/android/bluetooth/distributedjar.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = QtAndroidBluetooth
-include(bluetooth.pri)
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 35680c82..1b527ae3 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
@@ -48,6 +48,7 @@ import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -71,13 +72,21 @@ public class QtBluetoothLE {
private BluetoothGatt mBluetoothGatt = null;
private String mRemoteGattAddress;
private final UUID clientCharacteristicUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
+ private final int MAX_MTU = 512;
+ private final int DEFAULT_MTU = 23;
+ private int mSupportedMtu = -1;
/*
* The atomic synchronizes the timeoutRunnable thread and the response thread for the pending
* I/O job. Whichever thread comes first will pass the atomic gate. The other thread is
* cut short.
*/
- private AtomicInteger handleForTimeout = new AtomicInteger(-1); // -1 implies not running
+ // handle values above zero are for regular handle specific read/write requests
+ // handle values below zero are reserved for handle-independent requests
+ private int HANDLE_FOR_RESET = -1;
+ private int HANDLE_FOR_MTU_EXCHANGE = -2;
+ private AtomicInteger handleForTimeout = new AtomicInteger(HANDLE_FOR_RESET); // implies not running by default
+
private final int RUNNABLE_TIMEOUT = 3000; // 3 seconds
private final Handler timeoutHandler = new Handler(Looper.getMainLooper());
@@ -85,14 +94,18 @@ public class QtBluetoothLE {
public TimeoutRunnable(int handle) { pendingJobHandle = handle; }
@Override
public void run() {
- boolean timeoutStillValid = handleForTimeout.compareAndSet(pendingJobHandle, -1);
+ boolean timeoutStillValid = handleForTimeout.compareAndSet(pendingJobHandle, HANDLE_FOR_RESET);
if (timeoutStillValid) {
Log.w(TAG, "****** Timeout for request on handle " + (pendingJobHandle & 0xffff));
- Log.w(TAG, "****** Looks like the characteristic or descriptor does NOT act in " +
+ Log.w(TAG, "****** Looks like the peripheral does NOT act in " +
"accordance to Bluetooth 4.x spec.");
Log.w(TAG, "****** Please check server implementation. Continuing under " +
"reservation.");
- interruptCurrentIO(pendingJobHandle & 0xffff);
+
+ if (pendingJobHandle > HANDLE_FOR_RESET)
+ interruptCurrentIO(pendingJobHandle & 0xffff);
+ else if (pendingJobHandle < HANDLE_FOR_RESET)
+ interruptCurrentIO(pendingJobHandle);
}
}
@@ -187,10 +200,18 @@ public class QtBluetoothLE {
switch (status) {
case BluetoothGatt.GATT_SUCCESS:
errorCode = 0; break; //QLowEnergyController::NoError
+ case BluetoothGatt.GATT_FAILURE: // Android's equivalent of "do not know what error it is"
+ errorCode = 1; break; //QLowEnergyController::UnknownError
case 8: // BLE_HCI_CONNECTION_TIMEOUT
case 22: // BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION
Log.w(TAG, "Connection Error: Try to delay connect() call after previous activity");
errorCode = 5; break; //QLowEnergyController::ConnectionError
+ case 19: // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION
+ case 20: // BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES
+ case 21: // BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF
+ Log.w(TAG, "The remote host closed the connection");
+ errorCode = 7; //QLowEnergyController::RemoteHostClosedError
+ break;
default:
Log.w(TAG, "Unhandled error code on connectionStateChanged: " + status + " " + newState);
errorCode = status; break; //TODO deal with all errors
@@ -215,6 +236,8 @@ public class QtBluetoothLE {
errorCode = status; break; //TODO deal with all errors
}
leServicesDiscovered(qtObject, errorCode, builder.toString());
+
+ scheduleMtuExchange();
}
public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt,
@@ -239,7 +262,7 @@ public class QtBluetoothLE {
}
boolean requestTimedOut = !handleForTimeout.compareAndSet(
- modifiedReadWriteHandle(foundHandle, IoJobType.Read), -1);
+ modifiedReadWriteHandle(foundHandle, IoJobType.Read), HANDLE_FOR_RESET);
if (requestTimedOut) {
Log.w(TAG, "Late char read reply after timeout was hit for handle " + foundHandle);
// Timeout has hit before this response -> ignore the response
@@ -303,7 +326,7 @@ public class QtBluetoothLE {
}
boolean requestTimedOut = !handleForTimeout.compareAndSet(
- modifiedReadWriteHandle(handle, IoJobType.Write), -1);
+ modifiedReadWriteHandle(handle, IoJobType.Write), HANDLE_FOR_RESET);
if (requestTimedOut) {
Log.w(TAG, "Late char write reply after timeout was hit for handle " + handle);
// Timeout has hit before this response -> ignore the response
@@ -360,7 +383,7 @@ public class QtBluetoothLE {
}
boolean requestTimedOut = !handleForTimeout.compareAndSet(
- modifiedReadWriteHandle(foundHandle, IoJobType.Read), -1);
+ modifiedReadWriteHandle(foundHandle, IoJobType.Read), HANDLE_FOR_RESET);
if (requestTimedOut) {
Log.w(TAG, "Late descriptor read reply after timeout was hit for handle " +
foundHandle);
@@ -433,7 +456,7 @@ public class QtBluetoothLE {
int handle = handleForDescriptor(descriptor);
boolean requestTimedOut = !handleForTimeout.compareAndSet(
- modifiedReadWriteHandle(handle, IoJobType.Write), -1);
+ modifiedReadWriteHandle(handle, IoJobType.Write), HANDLE_FOR_RESET);
if (requestTimedOut) {
Log.w(TAG, "Late descriptor write reply after timeout was hit for handle " +
handle);
@@ -469,6 +492,32 @@ public class QtBluetoothLE {
// System.out.println("onReadRemoteRssi");
// }
+ // requires Android API v21
+ public void onMtuChanged(android.bluetooth.BluetoothGatt gatt, int mtu, int status)
+ {
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ Log.w(TAG, "MTU changed to " + mtu);
+ mSupportedMtu = mtu;
+ } else {
+ Log.w(TAG, "MTU change error " + status + ". New MTU " + mtu);
+ mSupportedMtu = DEFAULT_MTU;
+ }
+
+ boolean requestTimedOut = !handleForTimeout.compareAndSet(
+ modifiedReadWriteHandle(HANDLE_FOR_MTU_EXCHANGE, IoJobType.Mtu), HANDLE_FOR_RESET);
+ if (requestTimedOut) {
+ Log.w(TAG, "Late mtu reply after timeout was hit");
+ // Timeout has hit before this response -> ignore the response
+ // no need to unlock ioJobPending -> the timeout has done that already
+ return;
+ }
+
+ synchronized (readWriteQueue) {
+ ioJobPending = false;
+ }
+
+ performNextIO();
+ }
};
@@ -546,7 +595,7 @@ public class QtBluetoothLE {
private enum IoJobType
{
- Read, Write
+ Read, Write, Mtu
}
private class ReadWriteJob
@@ -722,7 +771,7 @@ public class QtBluetoothLE {
// kill all timeout handlers
timeoutHandler.removeCallbacksAndMessages(null);
- handleForTimeout.set(-1);
+ handleForTimeout.set(HANDLE_FOR_RESET);
synchronized (readWriteQueue) {
readWriteQueue.clear();
@@ -833,6 +882,42 @@ public class QtBluetoothLE {
handleDiscoveredService + 1, discoveredService.endHandle + 1);
}
+ private boolean executeMtuExchange()
+ {
+ if (Build.VERSION.SDK_INT >= 21) {
+ try {
+ Method mtuMethod = mBluetoothGatt.getClass().getDeclaredMethod("requestMtu", int.class);
+ if (mtuMethod != null) {
+ Boolean success = (Boolean) mtuMethod.invoke(mBluetoothGatt, MAX_MTU);
+ if (success.booleanValue()) {
+ Log.w(TAG, "MTU change initiated");
+ return false;
+ } else {
+ Log.w(TAG, "MTU change request failed");
+ }
+ }
+ } catch (Exception ex) {}
+ }
+
+ Log.w(TAG, "Assuming default MTU value of 23 bytes");
+
+ mSupportedMtu = DEFAULT_MTU;
+ return true;
+ }
+
+ private void scheduleMtuExchange()
+ {
+ ReadWriteJob newJob = new ReadWriteJob();
+ newJob.jobType = IoJobType.Mtu;
+ newJob.entry = null;
+
+ synchronized (readWriteQueue) {
+ readWriteQueue.add(newJob);
+ }
+
+ performNextIO();
+ }
+
/*
Internal Helper function for discoverServiceDetails()
@@ -1053,6 +1138,9 @@ public class QtBluetoothLE {
performNextIO();
+ if (handle == HANDLE_FOR_MTU_EXCHANGE)
+ return;
+
GattEntry entry = entries.get(handle);
if (entry == null)
return;
@@ -1077,24 +1165,28 @@ public class QtBluetoothLE {
boolean skip = false;
final ReadWriteJob nextJob;
- int handle = -1;
+ int handle = HANDLE_FOR_RESET;
synchronized (readWriteQueue) {
if (readWriteQueue.isEmpty() || ioJobPending)
return;
nextJob = readWriteQueue.remove();
- switch (nextJob.entry.type) {
- case Characteristic:
- handle = handleForCharacteristic(nextJob.entry.characteristic);
- break;
- case Descriptor:
- handle = handleForDescriptor(nextJob.entry.descriptor);
- break;
- case CharacteristicValue:
- handle = nextJob.entry.endHandle;
- default:
- break;
+ if (nextJob.jobType == IoJobType.Mtu) {
+ handle = HANDLE_FOR_MTU_EXCHANGE; //mtu request is special case
+ } else {
+ switch (nextJob.entry.type) {
+ case Characteristic:
+ handle = handleForCharacteristic(nextJob.entry.characteristic);
+ break;
+ case Descriptor:
+ handle = handleForDescriptor(nextJob.entry.descriptor);
+ break;
+ case CharacteristicValue:
+ handle = nextJob.entry.endHandle;
+ default:
+ break;
+ }
}
// timeout handler and handleForTimeout atomic must be setup before
@@ -1105,23 +1197,32 @@ public class QtBluetoothLE {
timeoutHandler.removeCallbacksAndMessages(null); // remove any timeout handlers
handleForTimeout.set(modifiedReadWriteHandle(handle, nextJob.jobType));
- if (nextJob.jobType == IoJobType.Read)
- skip = executeReadJob(nextJob);
- else
- skip = executeWriteJob(nextJob);
+ switch (nextJob.jobType) {
+ case Read:
+ skip = executeReadJob(nextJob);
+ break;
+ case Write:
+ skip = executeWriteJob(nextJob);
+ break;
+ case Mtu:
+ skip = executeMtuExchange();
+ break;
+ }
if (skip) {
- handleForTimeout.set(-1); // not a pending call -> release atomic
+ handleForTimeout.set(HANDLE_FOR_RESET); // not a pending call -> release atomic
} else {
ioJobPending = true;
timeoutHandler.postDelayed(new TimeoutRunnable(
modifiedReadWriteHandle(handle, nextJob.jobType)), RUNNABLE_TIMEOUT);
}
- Log.w(TAG, "Performing queued job, handle: " + handle + " " + nextJob.jobType + " (" +
+ if (nextJob.jobType != IoJobType.Mtu) {
+ Log.w(TAG, "Performing queued job, handle: " + handle + " " + nextJob.jobType + " (" +
(nextJob.requestedWriteType == BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) +
") ValueKnown: " + nextJob.entry.valueKnown + " Skipping: " + skip +
" " + nextJob.entry.type);
+ }
}
GattEntry entry = nextJob.entry;
@@ -1134,7 +1235,7 @@ public class QtBluetoothLE {
we have to report an error back to Qt. The error report is not required during
the initial service discovery though.
*/
- if (handle != -1) {
+ if (handle > HANDLE_FOR_RESET) {
// during service discovery we do not report error but emit characteristicRead()
// any other time a failure emits serviceError() signal
@@ -1163,15 +1264,16 @@ public class QtBluetoothLE {
break;
case CharacteristicValue:
// for more details see scheduleServiceDetailDiscovery(int)
- // ignore and continue unless last entry
- GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
- if (serviceEntry.endHandle == handle)
- finishCurrentServiceDiscovery(entry.associatedServiceHandle);
break;
case Service:
Log.w(TAG, "Scheduling of Service Gatt entry for service discovery should never happen.");
break;
}
+
+ // last entry of current discovery run?
+ GattEntry serviceEntry = entries.get(entry.associatedServiceHandle);
+ if (serviceEntry.endHandle == handle)
+ finishCurrentServiceDiscovery(entry.associatedServiceHandle);
} else {
int errorCode = 0;
@@ -1324,6 +1426,9 @@ public class QtBluetoothLE {
case Read:
modifiedHandle = (modifiedHandle | 0x00020000);
break;
+ case Mtu:
+ modifiedHandle = HANDLE_FOR_MTU_EXCHANGE;
+ break;
}
return modifiedHandle;
diff --git a/src/android/nfc/bundledjar.pro b/src/android/nfc/bundledjar.pro
deleted file mode 100644
index 37f7fc82..00000000
--- a/src/android/nfc/bundledjar.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TARGET = QtNfc-bundled
-CONFIG += bundled_jar_file
-include(nfc.pri)
diff --git a/src/android/nfc/distributedjar.pro b/src/android/nfc/distributedjar.pro
deleted file mode 100644
index ed65c50a..00000000
--- a/src/android/nfc/distributedjar.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = QtNfc
-include(nfc.pri)
diff --git a/src/android/nfc/nfc.pri b/src/android/nfc/nfc.pri
deleted file mode 100644
index 3f6e26aa..00000000
--- a/src/android/nfc/nfc.pri
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += java
-DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
-
-PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc
-
-JAVACLASSPATH += $$PWD/src/
-JAVASOURCES += \
- $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java
-
-# install
-target.path = $$[QT_INSTALL_PREFIX]/jar
-INSTALLS += target
diff --git a/src/android/nfc/nfc.pro b/src/android/nfc/nfc.pro
index 70373fe1..89026b75 100644
--- a/src/android/nfc/nfc.pro
+++ b/src/android/nfc/nfc.pro
@@ -1,3 +1,14 @@
-TEMPLATE = subdirs
-SUBDIRS += bundledjar.pro distributedjar.pro
+TARGET = QtNfc
+CONFIG += java
+DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
+
+PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc
+
+JAVACLASSPATH += $$PWD/src/
+JAVASOURCES += \
+ $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java
+
+# install
+target.path = $$[QT_INSTALL_PREFIX]/jar
+INSTALLS += target
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index 9c9c0409..131fb48d 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -120,7 +120,7 @@ static const MajorClassJavaToQtMapping majorMappings[] = {
{ "TOY", QBluetoothDeviceInfo::ToyDevice },
{ "UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedDevice },
{ "WEARABLE", QBluetoothDeviceInfo::WearableDevice },
- { Q_NULLPTR, QBluetoothDeviceInfo::UncategorizedDevice } //end of list
+ { nullptr, QBluetoothDeviceInfo::UncategorizedDevice } //end of list
};
// QBluetoothDeviceInfo::MajorDeviceClass value plus 1 matches index
@@ -164,7 +164,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "AUDIO_VIDEO_VIDEO_GAMING_TOY", QBluetoothDeviceInfo::GamingDevice },
{ "AUDIO_VIDEO_VIDEO_MONITOR", QBluetoothDeviceInfo::VideoMonitor },
{ "AUDIO_VIDEO_WEARABLE_HEADSET", QBluetoothDeviceInfo::WearableHeadsetDevice },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::ComputerDevice -> 7 entries
{ "COMPUTER_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedComputer }, // index 18
@@ -174,7 +174,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "COMPUTER_PALM_SIZE_PC_PDA", QBluetoothDeviceInfo::HandheldClamShellComputer },
{ "COMPUTER_SERVER", QBluetoothDeviceInfo::ServerComputer },
{ "COMPUTER_WEARABLE", QBluetoothDeviceInfo::WearableComputer },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::HealthDevice -> 8 entries
{ "HEALTH_BLOOD_PRESSURE", QBluetoothDeviceInfo::HealthBloodPressureMonitor }, // index 26
@@ -185,7 +185,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "HEALTH_THERMOMETER", QBluetoothDeviceInfo::HealthThermometer },
{ "HEALTH_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedHealthDevice },
{ "HEALTH_WEIGHING", QBluetoothDeviceInfo::HealthWeightScale },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::PhoneDevice -> 6 entries
{ "PHONE_CELLULAR", QBluetoothDeviceInfo::CellularPhone }, // index 35
@@ -194,7 +194,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "PHONE_MODEM_OR_GATEWAY", QBluetoothDeviceInfo::WiredModemOrVoiceGatewayPhone },
{ "PHONE_SMART", QBluetoothDeviceInfo::SmartPhone },
{ "PHONE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedPhone },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::ToyDevice -> 6 entries
{ "TOY_CONTROLLER", QBluetoothDeviceInfo::ToyController }, // index 42
@@ -203,7 +203,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "TOY_ROBOT", QBluetoothDeviceInfo::ToyRobot },
{ "TOY_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedToy },
{ "TOY_VEHICLE", QBluetoothDeviceInfo::ToyVehicle },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::WearableDevice -> 6 entries
{ "WEARABLE_GLASSES", QBluetoothDeviceInfo::WearableGlasses }, // index 49
@@ -212,7 +212,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "WEARABLE_PAGER", QBluetoothDeviceInfo::WearablePager },
{ "WEARABLE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedWearableDevice },
{ "WEARABLE_WRIST_WATCH", QBluetoothDeviceInfo::WearableWristWatch },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// QBluetoothDevice::PeripheralDevice -> 3 entries
// For some reason these are not mentioned in Android docs but still exist
@@ -220,24 +220,24 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ "PERIPHERAL_KEYBOARD", QBluetoothDeviceInfo::KeyboardPeripheral },
{ "PERIPHERAL_POINTING", QBluetoothDeviceInfo::PointingDevicePeripheral },
{ "PERIPHERAL_KEYBOARD_POINTING", QBluetoothDeviceInfo::KeyboardWithPointingDevicePeripheral },
- { Q_NULLPTR, 0 }, // separator
+ { nullptr, 0 }, // separator
// the following entries do not exist on Android
// we map them to the unknown minor version case
// QBluetoothDevice::Miscellaneous
- { Q_NULLPTR, 0 }, // index 61 & separator
+ { nullptr, 0 }, // index 61 & separator
// QBluetoothDevice::LANAccessDevice
- { Q_NULLPTR, 0 }, // index 62 & separator
+ { nullptr, 0 }, // index 62 & separator
// QBluetoothDevice::ImagingDevice
- { Q_NULLPTR, 0 }, // index 63 & separator
+ { nullptr, 0 }, // index 63 & separator
// QBluetoothDevice::UncategorizedDevice
- { Q_NULLPTR, 0 }, // index 64 & separator
+ { nullptr, 0 }, // index 64 & separator
};
-/*! Advertising Data Type (AD type) for LE scan records, as defined in Bluetooth CSS v6. */
+/* Advertising Data Type (AD type) for LE scan records, as defined in Bluetooth CSS v6. */
enum ADType {
ADType16BitUuidIncomplete = 0x02,
ADType16BitUuidComplete = 0x03,
@@ -308,7 +308,7 @@ QBluetoothDeviceInfo::MajorDeviceClass resolveAndroidMajorClass(jint javaType)
int i = 0;
jint fieldValue;
QBluetoothDeviceInfo::MajorDeviceClass result = QBluetoothDeviceInfo::UncategorizedDevice;
- while (majorMappings[i].javaFieldName != Q_NULLPTR) {
+ while (majorMappings[i].javaFieldName != nullptr) {
fieldValue = QAndroidJniObject::getStaticField<jint>(
javaBluetoothClassDeviceMajorClassName, majorMappings[i].javaFieldName);
if (env->ExceptionCheck()) {
@@ -359,7 +359,7 @@ void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major
int sizeIndex = minorIndexSizes[mappingIndex];
QAndroidJniEnvironment env;
- while (minorMappings[sizeIndex].javaFieldName != Q_NULLPTR) {
+ while (minorMappings[sizeIndex].javaFieldName != nullptr) {
jint fieldValue = QAndroidJniObject::getStaticField<jint>(
javaBluetoothClassDeviceClassName, minorMappings[sizeIndex].javaFieldName);
if (env->ExceptionCheck()) { // field lookup failed? skip it
diff --git a/src/bluetooth/android/inputstreamthread.cpp b/src/bluetooth/android/inputstreamthread.cpp
index ecd9218e..982c477b 100644
--- a/src/bluetooth/android/inputstreamthread.cpp
+++ b/src/bluetooth/android/inputstreamthread.cpp
@@ -77,6 +77,12 @@ qint64 InputStreamThread::bytesAvailable() const
return m_socket_p->buffer.size();
}
+bool InputStreamThread::canReadLine() const
+{
+ QMutexLocker locker(&m_mutex);
+ return m_socket_p->buffer.canReadLine();
+}
+
qint64 InputStreamThread::readData(char *data, qint64 maxSize)
{
QMutexLocker locker(&m_mutex);
diff --git a/src/bluetooth/android/inputstreamthread_p.h b/src/bluetooth/android/inputstreamthread_p.h
index 741333ac..a6ee0655 100644
--- a/src/bluetooth/android/inputstreamthread_p.h
+++ b/src/bluetooth/android/inputstreamthread_p.h
@@ -68,6 +68,7 @@ public:
explicit InputStreamThread(QBluetoothSocketPrivate *socket_p);
qint64 bytesAvailable() const;
+ bool canReadLine() const;
bool run();
qint64 readData(char *data, qint64 maxSize);
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp
index 68e291e5..176416c8 100644
--- a/src/bluetooth/android/jni_android.cpp
+++ b/src/bluetooth/android/jni_android.cpp
@@ -41,7 +41,7 @@
#include <jni.h>
#include <android/log.h>
#include <QtCore/QLoggingCategory>
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include "android/jni_android_p.h"
#include "android/androidbroadcastreceiver_p.h"
#include "android/serveracceptancethread_p.h"
diff --git a/src/bluetooth/android/lowenergynotificationhub.cpp b/src/bluetooth/android/lowenergynotificationhub.cpp
index 53f2d6cc..9f90e3de 100644
--- a/src/bluetooth/android/lowenergynotificationhub.cpp
+++ b/src/bluetooth/android/lowenergynotificationhub.cpp
@@ -41,7 +41,7 @@
#include <QtCore/QHash>
#include <QtCore/QLoggingCategory>
-#include <QtCore/QTime>
+#include <QtCore/QRandomGenerator>
#include <QtAndroidExtras/QAndroidJniEnvironment>
QT_BEGIN_NAMESPACE
@@ -81,11 +81,10 @@ LowEnergyNotificationHub::LowEnergyNotificationHub(const QBluetoothAddress &remo
}
// register C++ class pointer in Java
- qsrand(QTime::currentTime().msec());
lock.lockForWrite();
while (true) {
- javaToCtoken = qrand();
+ javaToCtoken = QRandomGenerator::get32();
if (!hubMap()->contains(javaToCtoken))
break;
}
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index 3f0c5604..e096374f 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -6,7 +6,7 @@ QMAKE_DOCS = $$PWD/doc/qtbluetooth.qdocconf
OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator
PUBLIC_HEADERS += \
- qbluetoothglobal.h \
+ qtbluetoothglobal.h \
qbluetoothaddress.h\
qbluetoothhostinfo.h \
qbluetoothuuid.h\
@@ -33,6 +33,7 @@ PUBLIC_HEADERS += \
qlowenergycontroller.h
PRIVATE_HEADERS += \
+ qtbluetoothglobal_p.h \
qbluetoothaddress_p.h\
qbluetoothhostinfo_p.h \
qbluetoothdeviceinfo_p.h\
@@ -77,6 +78,11 @@ SOURCES += \
qlowenergycontroller.cpp \
qlowenergyserviceprivate.cpp
+win32 {
+ WINDOWS_SDK_VERSION_STRING = $$(WindowsSDKVersion)
+ WINDOWS_SDK_VERSION = $$member($$list($$split(WINDOWS_SDK_VERSION_STRING, .)), 2)
+}
+
qtConfig(bluez) {
QT_PRIVATE = concurrent
QT_FOR_PRIVATE += dbus
@@ -120,8 +126,6 @@ qtConfig(bluez) {
android.permission.BLUETOOTH_ADMIN \
android.permission.ACCESS_COARSE_LOCATION # since Android 6.0 (API lvl 23)
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
- jar/QtAndroidBluetooth-bundled.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver
- ANDROID_JAR_DEPENDENCIES = \
jar/QtAndroidBluetooth.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver
SOURCES += \
@@ -183,15 +187,19 @@ qtConfig(bluez) {
qbluetoothserviceinfo_p.cpp \
qbluetoothservicediscoveryagent_p.cpp \
qbluetoothsocket_p.cpp \
- qbluetoothserver_p.cpp \
- qlowenergycontroller_p.cpp
+ qbluetoothserver_p.cpp
SOURCES -= qbluetoothdevicediscoveryagent.cpp
- SOURCES -= qlowenergycontroller_p.cpp
SOURCES -= qlowenergyservice.cpp
SOURCES -= qlowenergycontroller.cpp
-} else:winrt {
+} else: qtConfig(winrt_bt) {
DEFINES += QT_WINRT_BLUETOOTH
+ !winrt {
+ SOURCES += qbluetoothutils_win.cpp
+ DEFINES += CLASSIC_APP_BUILD
+ LIBS += runtimeobject.lib user32.lib
+ }
+
QT += core-private
SOURCES += \
@@ -203,11 +211,9 @@ qtConfig(bluez) {
qbluetoothsocket_winrt.cpp \
qlowenergycontroller_winrt.cpp
- WINRT_SDK_VERSION_STRING = $$(UCRTVersion)
- WINRT_SDK_VERSION = $$member($$list($$split(WINRT_SDK_VERSION_STRING, .)), 2)
- lessThan(WINRT_SDK_VERSION, 14393) {
+ lessThan(WINDOWS_SDK_VERSION, 14393) {
DEFINES += QT_WINRT_LIMITED_SERVICEDISCOVERY
- DEFINES += QT_UCRTVERSION=$$WINRT_SDK_VERSION
+ DEFINES += QT_UCRTVERSION=$$WINDOWS_SDK_VERSION
}
} else:win32 {
QT_PRIVATE = concurrent
diff --git a/src/bluetooth/bluez/adapter1_bluez5.cpp b/src/bluetooth/bluez/adapter1_bluez5.cpp
index 0f1e0acd..b1aefc8d 100644
--- a/src/bluetooth/bluez/adapter1_bluez5.cpp
+++ b/src/bluetooth/bluez/adapter1_bluez5.cpp
@@ -1,8 +1,8 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p adapter1 -v org.bluez.Adapter1.xml
+ * Command line was: qdbusxml2cpp -p adapter1_bluez5_p.h:adapter1_bluez5.cpp org.bluez.Adapter1.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/adapter1_bluez5_p.h b/src/bluetooth/bluez/adapter1_bluez5_p.h
index 5568da4c..ce108ad0 100644
--- a/src/bluetooth/bluez/adapter1_bluez5_p.h
+++ b/src/bluetooth/bluez/adapter1_bluez5_p.h
@@ -1,15 +1,15 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p adapter1 -v org.bluez.Adapter1.xml
+ * Command line was: qdbusxml2cpp -p adapter1_bluez5_p.h:adapter1_bluez5.cpp org.bluez.Adapter1.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 ADAPTER1_H_1396951555
-#define ADAPTER1_H_1396951555
+#ifndef ADAPTER1_BLUEZ5_P_H
+#define ADAPTER1_BLUEZ5_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.Adapter1"; }
public:
- OrgBluezAdapter1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezAdapter1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezAdapter1Interface();
@@ -100,19 +100,26 @@ public Q_SLOTS: // METHODS
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(device);
- return asyncCallWithArgumentList(QLatin1String("RemoveDevice"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("RemoveDevice"), argumentList);
+ }
+
+ inline QDBusPendingReply<> SetDiscoveryFilter(const QVariantMap &properties)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(properties);
+ return asyncCallWithArgumentList(QStringLiteral("SetDiscoveryFilter"), 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);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/bluetoothmanagement.cpp b/src/bluetooth/bluez/bluetoothmanagement.cpp
new file mode 100644
index 00000000..9df74b34
--- /dev/null
+++ b/src/bluetooth/bluez/bluetoothmanagement.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** 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 <QtCore/qloggingcategory.h>
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/qtimer.h>
+
+#include "bluetoothmanagement_p.h"
+#include "bluez_data_p.h"
+#include "../qbluetoothsocket_p.h"
+
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <linux/capability.h>
+
+
+QT_BEGIN_NAMESPACE
+
+// Packet data structures for Mgmt API bluez.git/doc/mgmt-api.txt
+
+enum class EventCode {
+ DeviceFound = 0x0012,
+};
+
+struct MgmtHdr {
+ quint16 cmdCode;
+ quint16 controllerIndex;
+ quint16 length;
+} __attribute__((packed));
+
+struct MgmtEventDeviceFound {
+ bdaddr_t bdaddr;
+ quint8 type;
+ quint8 rssi;
+ quint32 flags;
+ quint16 eirLength;
+ quint8 eirData[0];
+} __attribute__((packed));
+
+
+/*
+ * This class encapsulates access to the Bluetooth Management API as introduced by
+ * Linux kernel 3.4. Some Bluetooth information is not exposed via the usual DBus
+ * API (e.g. the random/public address type info). In those cases we have to fall back
+ * to this mgmt API.
+ *
+ * Note that opening such a Bluetooth mgmt socket requires CAP_NET_ADMIN (root) capability.
+ *
+ * Documentation can be found in bluez-git/doc/mgmt-api.txt
+ */
+
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
+
+// These structs and defines come straight from linux/capability.h.
+// To avoid missing definitions we re-define them if not existing.
+// In addition, we don't want to pull in a libcap2 dependency
+struct capHdr {
+ quint32 version;
+ int pid;
+};
+
+struct capData {
+ quint32 effective;
+ quint32 permitted;
+ quint32 inheritable;
+};
+
+#ifndef _LINUX_CAPABILITY_VERSION_3
+#define _LINUX_CAPABILITY_VERSION_3 0x20080522
+#endif
+
+#ifndef _LINUX_CAPABILITY_U32S_3
+#define _LINUX_CAPABILITY_U32S_3 2
+#endif
+
+#ifndef CAP_NET_ADMIN
+#define CAP_NET_ADMIN 12
+#endif
+
+#ifndef CAP_TO_INDEX
+#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */
+#endif
+
+#ifndef CAP_TO_MASK
+#define CAP_TO_MASK(x) (1 << ((x) & 31)) /* mask for indexed __u32 */
+#endif
+
+const int msecInADay = 1000*60*60*24;
+
+inline uint qHash(const QBluetoothAddress& address)
+{
+ return qHash(address.toUInt64());
+}
+
+static int sysCallCapGet(capHdr *header, capData *data)
+{
+ return syscall(__NR_capget, header, data);
+}
+
+/*!
+ * Checks that the current process has the effective CAP_NET_ADMIN permission.
+ */
+static bool hasBtMgmtPermission()
+{
+ // We only care for cap version 3 introduced by kernel 2.6.26
+ // because the new BlueZ management API only exists since kernel 3.4.
+
+ struct capHdr header = {};
+ struct capData data[_LINUX_CAPABILITY_U32S_3] = {{}};
+ header.version = _LINUX_CAPABILITY_VERSION_3;
+ header.pid = getpid();
+
+ if (sysCallCapGet(&header, data) < 0) {
+ qCWarning(QT_BT_BLUEZ, "BluetoothManangement: getCap failed with %s",
+ qPrintable(qt_error_string(errno)));
+ return false;
+ }
+
+ return (data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective & CAP_TO_MASK(CAP_NET_ADMIN));
+}
+
+BluetoothManagement::BluetoothManagement(QObject *parent) : QObject(parent)
+{
+ bool hasPermission = hasBtMgmtPermission();
+ if (!hasPermission) {
+ qCInfo(QT_BT_BLUEZ, "Missing CAP_NET_ADMIN permission. Cannot determine whether "
+ "a found address is of random or public type.");
+ return;
+ }
+
+ sockaddr_hci hciAddr;
+
+ fd = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
+ if (fd < 0) {
+ qCWarning(QT_BT_BLUEZ, "Cannot open Bluetooth Management socket: %s",
+ qPrintable(qt_error_string(errno)));
+ return;
+ }
+
+ memset(&hciAddr, 0, sizeof(hciAddr));
+ hciAddr.hci_dev = HCI_DEV_NONE;
+ hciAddr.hci_channel = HCI_CHANNEL_CONTROL;
+ hciAddr.hci_family = AF_BLUETOOTH;
+
+ if (::bind(fd, (struct sockaddr *)(&hciAddr), sizeof(hciAddr)) < 0) {
+ qCWarning(QT_BT_BLUEZ, "Cannot bind Bluetooth Management socket: %s",
+ qPrintable(qt_error_string(errno)));
+ ::close(fd);
+ fd = -1;
+ return;
+ }
+
+ notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(notifier, &QSocketNotifier::activated, this, &BluetoothManagement::_q_readNotifier);
+
+ // ensure cache is regularly cleaned (once every 24h)
+ QTimer* timer = new QTimer(this);
+ timer->setInterval(msecInADay);
+ timer->setTimerType(Qt::VeryCoarseTimer);
+ connect(timer, &QTimer::timeout, this, &BluetoothManagement::cleanupOldAddressFlags);
+ timer->start();
+}
+
+Q_GLOBAL_STATIC(BluetoothManagement, bluetoothKernelManager)
+
+BluetoothManagement *BluetoothManagement::instance()
+{
+ return bluetoothKernelManager();
+}
+
+void BluetoothManagement::_q_readNotifier()
+{
+ char *dst = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE);
+ int readCount = ::read(fd, dst, QPRIVATELINEARBUFFER_BUFFERSIZE);
+ buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readCount < 0 ? 0 : readCount));
+ if (readCount < 0) {
+ qCWarning(QT_BT_BLUEZ, "Management Control read error %s", qPrintable(qt_error_string(errno)));
+ return;
+ }
+
+ // do we have at least one complete mgmt header?
+ if ((uint)buffer.size() < sizeof(MgmtHdr))
+ return;
+
+ QByteArray data = buffer.readAll();
+
+ while (true) {
+ if ((uint)data.size() < sizeof(MgmtHdr))
+ break;
+
+ const MgmtHdr *hdr = reinterpret_cast<const MgmtHdr*>(data.constData());
+ const int nextPackageSize = qFromLittleEndian(hdr->length) + sizeof(MgmtHdr);
+ const int remainingPackageSize = data.length() - nextPackageSize;
+
+ if (data.length() < nextPackageSize)
+ break; // not a complete event header -> wait for next notifier
+
+ switch (static_cast<EventCode>(qFromLittleEndian(hdr->cmdCode))) {
+ case EventCode::DeviceFound:
+ {
+ const MgmtEventDeviceFound *event = reinterpret_cast<const MgmtEventDeviceFound*>
+ (data.constData() + sizeof(MgmtHdr));
+
+ if (event->type == BDADDR_LE_RANDOM) {
+ const bdaddr_t address = event->bdaddr;
+ quint64 bdaddr;
+
+ convertAddress(address.b, &bdaddr);
+ const QBluetoothAddress qtAddress(bdaddr);
+ qCDebug(QT_BT_BLUEZ) << "BluetoothManagement: found random device"
+ << qtAddress;
+ processRandomAddressFlagInformation(qtAddress);
+ }
+
+ break;
+ }
+ default:
+ qCDebug(QT_BT_BLUEZ) << "BluetoothManagement: Ignored event:"
+ << hex << qFromLittleEndian(hdr->cmdCode);
+ break;
+ }
+
+ if (data.length() > nextPackageSize)
+ data = data.right(remainingPackageSize);
+ else
+ data.clear();
+
+ if (data.isEmpty())
+ break;
+ }
+
+ if (!data.isEmpty())
+ buffer.ungetBlock(data.constData(), data.size());
+}
+
+void BluetoothManagement::processRandomAddressFlagInformation(const QBluetoothAddress &address)
+{
+ // insert or update
+ QMutexLocker locker(&accessLock);
+ privateFlagAddresses[address] = QDateTime::currentDateTimeUtc();
+}
+
+/*
+ * Ensure that private address cache is not older than 24h.
+ */
+void BluetoothManagement::cleanupOldAddressFlags()
+{
+ const auto cutOffTime = QDateTime::currentDateTimeUtc().addDays(-1);
+
+ QMutexLocker locker(&accessLock);
+
+ auto i = privateFlagAddresses.begin();
+ while (i != privateFlagAddresses.end()) {
+ if (i.value() < cutOffTime)
+ i = privateFlagAddresses.erase(i);
+ else
+ i++;
+ }
+}
+
+bool BluetoothManagement::isAddressRandom(const QBluetoothAddress &address) const
+{
+ if (fd == -1 || address.isNull())
+ return false;
+
+ QMutexLocker locker(&accessLock);
+ return privateFlagAddresses.contains(address);
+}
+
+bool BluetoothManagement::isMonitoringEnabled() const
+{
+ return (fd == -1) ? false : true;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/bluez/bluetoothmanagement_p.h b/src/bluetooth/bluez/bluetoothmanagement_p.h
new file mode 100644
index 00000000..954f6e03
--- /dev/null
+++ b/src/bluetooth/bluez/bluetoothmanagement_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 BLUETOOTHMANAGEMENT_P_H
+#define BLUETOOTHMANAGEMENT_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 <QtCore/qdatetime.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qobject.h>
+
+#include <QtBluetooth/qbluetoothaddress.h>
+
+#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE
+#define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384)
+#endif
+#include "../qprivatelinearbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class BluetoothManagement : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit BluetoothManagement(QObject *parent = nullptr);
+ static BluetoothManagement *instance();
+
+ bool isAddressRandom(const QBluetoothAddress &address) const;
+ bool isMonitoringEnabled() const;
+
+private slots:
+ void _q_readNotifier();
+ void processRandomAddressFlagInformation(const QBluetoothAddress &address);
+ void cleanupOldAddressFlags();
+
+private:
+ void readyRead();
+
+ int fd = -1;
+ QSocketNotifier* notifier;
+ QPrivateLinearBuffer buffer;
+ QHash<QBluetoothAddress, QDateTime> privateFlagAddresses;
+ mutable QMutex accessLock;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // BLUETOOTHMANAGEMENT_P_H
diff --git a/src/bluetooth/bluez/bluez.pri b/src/bluetooth/bluez/bluez.pri
index 46727cbc..b99f2712 100644
--- a/src/bluetooth/bluez/bluez.pri
+++ b/src/bluetooth/bluez/bluez.pri
@@ -18,7 +18,9 @@ HEADERS += bluez/manager_p.h \
bluez/obex_objectpush1_bluez5_p.h \
bluez/obex_transfer1_bluez5_p.h \
bluez/bluez_data_p.h \
- bluez/hcimanager_p.h
+ bluez/hcimanager_p.h \
+ bluez/remotedevicemanager_p.h \
+ bluez/bluetoothmanagement_p.h
SOURCES += bluez/manager.cpp \
bluez/adapter.cpp \
@@ -39,4 +41,6 @@ SOURCES += bluez/manager.cpp \
bluez/obex_client1_bluez5.cpp \
bluez/obex_objectpush1_bluez5.cpp \
bluez/obex_transfer1_bluez5.cpp \
- bluez/hcimanager.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 8871a872..de41003f 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -69,6 +69,7 @@ bool isBluez5()
qDBusRegisterMetaType<InterfaceList>();
qDBusRegisterMetaType<ManagedObjectList>();
+ qDBusRegisterMetaType<ManufacturerDataList>();
QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
reply.waitForFinished();
diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h
index a46810fc..2d72caf1 100644
--- a/src/bluetooth/bluez/bluez5_helper_p.h
+++ b/src/bluetooth/bluez/bluez5_helper_p.h
@@ -57,8 +57,10 @@
typedef QMap<QString, QVariantMap> InterfaceList;
typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;
+typedef QMap<quint16, QDBusVariant> ManufacturerDataList;
Q_DECLARE_METATYPE(InterfaceList)
+Q_DECLARE_METATYPE(ManufacturerDataList)
Q_DECLARE_METATYPE(ManagedObjectList)
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h
index 8c2dc43e..684cd5b8 100644
--- a/src/bluetooth/bluez/bluez_data_p.h
+++ b/src/bluetooth/bluez/bluez_data_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** 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.
@@ -99,6 +99,10 @@ struct bt_security {
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
+#define SCO_LINK 0x00
+#define ACL_LINK 0x01
+#define ESCO_LINK 0x02
+#define LE_LINK 0x80 // based on hcitool.c -> no fixed constant available
/* Byte order conversions */
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -200,7 +204,10 @@ template<> inline void putBtData(quint128 src, void *dst)
// HCI related
-#define HCI_MAX_DEV 16
+#define HCI_MAX_DEV 16
+#define HCI_DEV_NONE 0xffff
+
+#define HCI_CHANNEL_CONTROL 0x3
#define HCI_MAX_EVENT_SIZE 260
diff --git a/src/bluetooth/bluez/device1_bluez5.cpp b/src/bluetooth/bluez/device1_bluez5.cpp
index a4c01d3f..491a365d 100644
--- a/src/bluetooth/bluez/device1_bluez5.cpp
+++ b/src/bluetooth/bluez/device1_bluez5.cpp
@@ -1,8 +1,7 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p device1_bluez5 -v org.bluez.Device1.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/device1_bluez5_p.h b/src/bluetooth/bluez/device1_bluez5_p.h
index d6181b34..4feb5318 100644
--- a/src/bluetooth/bluez/device1_bluez5_p.h
+++ b/src/bluetooth/bluez/device1_bluez5_p.h
@@ -1,15 +1,14 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
- * Command line was: qdbusxml2cpp -p device1_bluez5 -v org.bluez.Device1.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 DEVICE1_BLUEZ5_H_1396951960
-#define DEVICE1_BLUEZ5_H_1396951960
+#ifndef DEVICE1_BLUEZ5_P_H
+#define DEVICE1_BLUEZ5_P_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
@@ -19,6 +18,7 @@
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
+#include "bluez5_helper_p.h"
/*
* Proxy class for interface org.bluez.Device1
@@ -31,7 +31,7 @@ public:
{ return "org.bluez.Device1"; }
public:
- OrgBluezDevice1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ OrgBluezDevice1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~OrgBluezDevice1Interface();
@@ -75,6 +75,10 @@ public:
inline bool legacyPairing() const
{ return qvariant_cast< bool >(property("LegacyPairing")); }
+ Q_PROPERTY(ManufacturerDataList ManufacturerData READ manufacturerData)
+ inline ManufacturerDataList manufacturerData() const
+ { return qvariant_cast< ManufacturerDataList >(property("ManufacturerData")); }
+
Q_PROPERTY(QString Modalias READ modalias)
inline QString modalias() const
{ return qvariant_cast< QString >(property("Modalias")); }
@@ -91,12 +95,24 @@ public:
inline short rSSI() const
{ return qvariant_cast< short >(property("RSSI")); }
+ Q_PROPERTY(QVariantMap ServiceData READ serviceData)
+ inline QVariantMap serviceData() const
+ { return qvariant_cast< QVariantMap >(property("ServiceData")); }
+
+ Q_PROPERTY(bool ServicesResolved READ servicesResolved)
+ inline bool servicesResolved() const
+ { return qvariant_cast< bool >(property("ServicesResolved")); }
+
Q_PROPERTY(bool Trusted READ trusted WRITE setTrusted)
inline bool trusted() const
{ return qvariant_cast< bool >(property("Trusted")); }
inline void setTrusted(bool value)
{ setProperty("Trusted", QVariant::fromValue(value)); }
+ Q_PROPERTY(short TxPower READ txPower)
+ inline short txPower() const
+ { return qvariant_cast< short >(property("TxPower")); }
+
Q_PROPERTY(QStringList UUIDs READ uUIDs)
inline QStringList uUIDs() const
{ return qvariant_cast< QStringList >(property("UUIDs")); }
@@ -105,39 +121,39 @@ public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CancelPairing()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("CancelPairing"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("CancelPairing"), argumentList);
}
inline QDBusPendingReply<> Connect()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Connect"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Connect"), argumentList);
}
inline QDBusPendingReply<> ConnectProfile(const QString &UUID)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(UUID);
- return asyncCallWithArgumentList(QLatin1String("ConnectProfile"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("ConnectProfile"), argumentList);
}
inline QDBusPendingReply<> Disconnect()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Disconnect"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Disconnect"), argumentList);
}
inline QDBusPendingReply<> DisconnectProfile(const QString &UUID)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(UUID);
- return asyncCallWithArgumentList(QLatin1String("DisconnectProfile"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("DisconnectProfile"), argumentList);
}
inline QDBusPendingReply<> Pair()
{
QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("Pair"), argumentList);
+ return asyncCallWithArgumentList(QStringLiteral("Pair"), argumentList);
}
Q_SIGNALS: // SIGNALS
diff --git a/src/bluetooth/bluez/generate b/src/bluetooth/bluez/generate
index 14bcaea8..cdba18c4 100755
--- a/src/bluetooth/bluez/generate
+++ b/src/bluetooth/bluez/generate
@@ -1,5 +1,6 @@
#!/bin/sh
+#Bluez 4
qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager
qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter
qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device
@@ -9,8 +10,13 @@ qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openo
qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client
qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer
qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent
-#qdbusxml2cpp -p serialproxymanager_p.h:serialproxymanager.cpp org.bluez.all.xml org.bluez.SerialProxyManager
-#qdbusxml2cpp -p networkpeer_p.h:networkpeer.cpp org.bluez.all.xml org.bluez.NetworkPeer
-#qdbusxml2cpp -p networkhub_p.h:networkhub.cpp org.bluez.all.xml org.bluez.NetworkHub
-#qdbusxml2cpp -p networkrouter_p.h:networkrouter.cpp org.bluez.all.xml org.bluez.NetworkRouter
+#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 -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml
+qdbusxml2cpp -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
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index 93bf941b..c524117c 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -288,6 +288,50 @@ QBluetoothAddress HciManager::addressForConnectionHandle(quint16 handle) const
return QBluetoothAddress();
}
+QVector<quint16> HciManager::activeLowEnergyConnections() const
+{
+ if (!isValid())
+ return QVector<quint16>();
+
+ hci_conn_info *info;
+ hci_conn_list_req *infoList;
+
+ const int maxNoOfConnections = 20;
+ infoList = (hci_conn_list_req *)
+ malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info));
+
+ if (!infoList)
+ return QVector<quint16>();
+
+ QScopedPointer<hci_conn_list_req, QScopedPointerPodDeleter> p(infoList);
+ p->conn_num = maxNoOfConnections;
+ p->dev_id = hciDev;
+ info = p->conn_info;
+
+ if (ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot retrieve connection list";
+ return QVector<quint16>();
+ }
+
+ QVector<quint16> activeLowEnergyHandles;
+ for (int i = 0; i < infoList->conn_num; i++) {
+ switch (info[i].type) {
+ case SCO_LINK:
+ case ACL_LINK:
+ case ESCO_LINK:
+ continue;
+ case LE_LINK:
+ activeLowEnergyHandles.append(info[i].handle);
+ break;
+ default:
+ qCWarning(QT_BT_BLUEZ) << "Unknown active connection type:" << hex << info[i].type;
+ break;
+ }
+ }
+
+ return activeLowEnergyHandles;
+}
+
quint16 forceIntervalIntoRange(double connectionInterval)
{
return qMin<double>(qMax<double>(7.5, connectionInterval), 4000) / 1.25;
diff --git a/src/bluetooth/bluez/hcimanager_p.h b/src/bluetooth/bluez/hcimanager_p.h
index 3bae92e5..3127a747 100644
--- a/src/bluetooth/bluez/hcimanager_p.h
+++ b/src/bluetooth/bluez/hcimanager_p.h
@@ -55,6 +55,7 @@
#include <QtCore/QSet>
#include <QtCore/QSocketNotifier>
#include <QtBluetooth/QBluetoothAddress>
+#include <QVector>
#include "bluez/bluez_data_p.h"
QT_BEGIN_NAMESPACE
@@ -82,6 +83,9 @@ public:
void stopEvents();
QBluetoothAddress addressForConnectionHandle(quint16 handle) const;
+ // active connections
+ QVector<quint16> activeLowEnergyConnections() const;
+
bool sendConnectionUpdateCommand(quint16 handle, const QLowEnergyConnectionParameters &params);
bool sendConnectionParameterUpdateRequest(quint16 handle,
const QLowEnergyConnectionParameters &params);
diff --git a/src/bluetooth/bluez/objectmanager_p.h b/src/bluetooth/bluez/objectmanager_p.h
index 823badeb..74f5ab43 100644
--- a/src/bluetooth/bluez/objectmanager_p.h
+++ b/src/bluetooth/bluez/objectmanager_p.h
@@ -20,10 +20,6 @@
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
-/* Temporary hack to merge branches until Bluez headers are removed
- * from bluez5_helpers_p.h.
- */
-#define NO_BLUEZ_INCLUDES
#include "bluez5_helper_p.h"
/*
diff --git a/src/bluetooth/bluez/org.bluez.Adapter1.xml b/src/bluetooth/bluez/org.bluez.Adapter1.xml
index a1e6babe..121c277e 100644
--- a/src/bluetooth/bluez/org.bluez.Adapter1.xml
+++ b/src/bluetooth/bluez/org.bluez.Adapter1.xml
@@ -7,6 +7,10 @@
<method name="RemoveDevice">
<arg name="device" type="o" direction="in"/>
</method>
+ <method name="SetDiscoveryFilter">
+ <arg name="properties" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+ </method>
<property name="Address" type="s" access="read"></property>
<property name="Name" type="s" access="read"></property>
<property name="Alias" type="s" access="readwrite"></property>
diff --git a/src/bluetooth/bluez/org.bluez.Device1.xml b/src/bluetooth/bluez/org.bluez.Device1.xml
index 1f8fd2c1..554d0b53 100644
--- a/src/bluetooth/bluez/org.bluez.Device1.xml
+++ b/src/bluetooth/bluez/org.bluez.Device1.xml
@@ -27,5 +27,15 @@
<property name="UUIDs" type="as" access="read"></property>
<property name="Modalias" type="s" access="read"></property>
<property name="Adapter" type="o" access="read"></property>
+ <!-- ManufacturerData & ServiceData introduced by Bluez 5.31 -->
+ <property name="ManufacturerData" type="a{qv}" access="read">
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="ManufacturerDataList"/>
+ </property>
+ <property name="ServiceData" type="a{sv}" access="read">
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="QVariantMap"/>
+ </property>
+ <!-- TxPower and ServicesResolved introduced by Bluez 5.42 -->
+ <property name="TxPower" type="n" access="read"></property>
+ <property name="ServicesResolved" type="b" access="read"></property>
</interface>
</node>
diff --git a/src/bluetooth/bluez/remotedevicemanager.cpp b/src/bluetooth/bluez/remotedevicemanager.cpp
new file mode 100644
index 00000000..f63b21e6
--- /dev/null
+++ b/src/bluetooth/bluez/remotedevicemanager.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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 <QtCore/QLoggingCategory>
+
+#include "remotedevicemanager_p.h"
+#include "bluez5_helper_p.h"
+#include "device1_bluez5_p.h"
+#include "objectmanager_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
+
+/*!
+ * Convenience wrapper around org.bluez.Device1 management
+ *
+ * Very simple and not thread safe.
+ */
+
+RemoteDeviceManager::RemoteDeviceManager(
+ const QBluetoothAddress &address, QObject *parent)
+ : QObject(parent), localAddress(address)
+{
+ if (!isBluez5())
+ return;
+
+ bool ok = false;
+ adapterPath = findAdapterForAddress(address, &ok);
+ if (!ok || adapterPath.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot initialize RemoteDeviceManager";
+ }
+}
+
+bool RemoteDeviceManager::scheduleJob(
+ JobType job, const QVector<QBluetoothAddress> &remoteDevices)
+{
+ if (adapterPath.isEmpty())
+ return false;
+
+ for (const auto& remote : remoteDevices)
+ jobQueue.push_back(std::make_pair(job, remote));
+
+ QTimer::singleShot(0, this, [this](){ runQueue(); });
+ return true;
+}
+
+void RemoteDeviceManager::runQueue()
+{
+ if (jobInProgress || adapterPath.isEmpty())
+ return;
+
+ if (jobQueue.empty())
+ return;
+
+ jobInProgress = true;
+ switch (jobQueue.front().first) {
+ case JobType::JobDisconnectDevice:
+ disconnectDevice(jobQueue.front().second);
+ break;
+ default:
+ break;
+ }
+}
+
+void RemoteDeviceManager::prepareNextJob()
+{
+ Q_ASSERT(!jobQueue.empty());
+
+ jobQueue.pop_front();
+ jobInProgress = false;
+
+ if (jobQueue.empty())
+ emit finished();
+ else
+ runQueue();
+}
+
+void RemoteDeviceManager::disconnectDevice(const QBluetoothAddress &remote)
+{
+ // collect initial set of information
+ OrgFreedesktopDBusObjectManagerInterface managerBluez5(
+ QStringLiteral("org.bluez"),
+ QStringLiteral("/"),
+ QDBusConnection::systemBus(), this);
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez5.GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ QTimer::singleShot(0, this, [this](){ prepareNextJob(); });
+ return;
+ }
+
+ bool jobStarted = false;
+ ManagedObjectList managedObjectList = reply.value();
+ for (auto it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
+ const QDBusObjectPath &path = it.key();
+ const InterfaceList &ifaceList = it.value();
+
+ for (auto jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
+ const QString &iface = jt.key();
+
+ if (path.path().indexOf(adapterPath) != 0)
+ continue; //devices whose path doesn't start with same path we skip
+
+ if (iface != QStringLiteral("org.bluez.Device1"))
+ continue;
+
+ const QBluetoothAddress foundAddress(ifaceList.value(iface).value(QStringLiteral("Address")).toString());
+ if (foundAddress != remote)
+ continue;
+
+ // found the correct Device1 path
+ OrgBluezDevice1Interface* device1 = new OrgBluezDevice1Interface(QStringLiteral("org.bluez"),
+ path.path(),
+ QDBusConnection::systemBus(),
+ this);
+ QDBusPendingReply<> asyncReply = device1->Disconnect();
+ QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(asyncReply, this);
+ const auto watcherFinished = [this, device1](QDBusPendingCallWatcher* call) {
+ call->deleteLater();
+ device1->deleteLater();
+ prepareNextJob();
+ };
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, watcherFinished);
+ jobStarted = true;
+ break;
+ }
+ }
+
+ if (!jobStarted)
+ QTimer::singleShot(0, this, [this](){ prepareNextJob(); });
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/bluez/remotedevicemanager_p.h b/src/bluetooth/bluez/remotedevicemanager_p.h
new file mode 100644
index 00000000..a6af8f44
--- /dev/null
+++ b/src/bluetooth/bluez/remotedevicemanager_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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 REMOTEDEVICEMANAGER_P_H
+#define REMOTEDEVICEMANAGER_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 <deque>
+
+#include <QMutex>
+#include <QObject>
+#include <QVector>
+
+#include <QtBluetooth/qbluetoothaddress.h>
+
+
+QT_BEGIN_NAMESPACE
+
+// This API is kept a bit more generic in anticipation of further changes in the future.
+
+class RemoteDeviceManager : public QObject
+{
+ Q_OBJECT
+public:
+ enum class JobType
+ {
+ JobDisconnectDevice,
+ };
+
+ explicit RemoteDeviceManager(const QBluetoothAddress& localAddress, QObject *parent = 0);
+
+ bool isJobInProgress() const { return jobInProgress; }
+ bool scheduleJob(JobType job, const QVector<QBluetoothAddress>& remoteDevices);
+
+signals:
+ void finished();
+
+private slots:
+ void runQueue();
+ void prepareNextJob();
+
+private:
+ void disconnectDevice(const QBluetoothAddress& remote);
+
+ bool jobInProgress = false;
+ QBluetoothAddress localAddress;
+ std::deque<std::pair<JobType, QBluetoothAddress>> jobQueue;
+ QString adapterPath;
+};
+
+QT_END_NAMESPACE
+
+#endif // REMOTEDEVICEMANAGER_P_H
diff --git a/src/bluetooth/configure.json b/src/bluetooth/configure.json
index a1e65000..3153aca6 100644
--- a/src/bluetooth/configure.json
+++ b/src/bluetooth/configure.json
@@ -23,6 +23,11 @@
"label": "Linux Crypto API",
"type": "compile",
"test": "linux_crypto_api"
+ },
+ "winrt_bt": {
+ "label": "WinRT Bluetooth API",
+ "type": "compile",
+ "test": "winrt_bt"
}
},
@@ -41,6 +46,11 @@
"label": "Linux Crypto API",
"condition": "features.bluez_le && tests.linux_crypto_api",
"output": [ "privateFeature" ]
+ },
+ "winrt_bt": {
+ "label": "WinRT Bluetooth API (desktop & UWP)",
+ "condition": "config.win32 && tests.winrt_bt",
+ "output": [ "privateFeature" ]
}
},
@@ -64,7 +74,8 @@ Only classic Bluetooth will be available."
"entries": [
"bluez",
"bluez_le",
- "linux_crypto_api"
+ "linux_crypto_api",
+ "winrt_bt"
]
}
]
diff --git a/src/bluetooth/doc/qtbluetooth.qdocconf b/src/bluetooth/doc/qtbluetooth.qdocconf
index aa485cdb..a994652b 100644
--- a/src/bluetooth/doc/qtbluetooth.qdocconf
+++ b/src/bluetooth/doc/qtbluetooth.qdocconf
@@ -48,6 +48,7 @@ exampledirs += ../../../examples/bluetooth \
../
manifestmeta.thumbnail.names = "QtBluetooth/Bluetooth Low Energy Heart Rate Server Example"
+manifestmeta.highlighted.names += "QtBluetooth/Bluetooth Low Energy Heart Rate Game"
imagedirs += images
diff --git a/src/bluetooth/doc/src/bluetooth-cpp.qdoc b/src/bluetooth/doc/src/bluetooth-cpp.qdoc
index ae39772f..26cd060b 100644
--- a/src/bluetooth/doc/src/bluetooth-cpp.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-cpp.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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 local connectivty modules.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc
index d2db7aa3..9cb5f3b2 100644
--- a/src/bluetooth/doc/src/bluetooth-index.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-index.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
index a29f88d0..60181240 100644
--- a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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 local connectivty modules.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/doc/src/bluetooth-overview.qdoc b/src/bluetooth/doc/src/bluetooth-overview.qdoc
index 1b712f23..8138e937 100644
--- a/src/bluetooth/doc/src/bluetooth-overview.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-overview.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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 local connectivty modules.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/doc/src/bluetooth-qml.qdoc b/src/bluetooth/doc/src/bluetooth-qml.qdoc
index 2fb64f45..51aa5a25 100644
--- a/src/bluetooth/doc/src/bluetooth-qml.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-qml.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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 local connectivty modules.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/doc/src/examples.qdoc b/src/bluetooth/doc/src/examples.qdoc
index 32152c84..e33ae4d8 100644
--- a/src/bluetooth/doc/src/examples.qdoc
+++ b/src/bluetooth/doc/src/examples.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** 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.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/bluetooth/osx/osxbluetooth_p.h b/src/bluetooth/osx/osxbluetooth_p.h
index 93842e77..ea1b388f 100644
--- a/src/bluetooth/osx/osxbluetooth_p.h
+++ b/src/bluetooth/osx/osxbluetooth_p.h
@@ -54,47 +54,10 @@
#include <QtCore/qglobal.h>
-#ifndef QT_OSX_BLUETOOTH
-
#include <CoreBluetooth/CoreBluetooth.h>
-#else
-
-#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
-
-#include <CoreBluetooth/CoreBluetooth.h>
-#include <IOBluetooth/IOBluetooth.h>
-
-#else
-
-// CoreBluetooth with SDK 10.9 seems to be broken: the class CBPeripheralManager is enabled on macOS
-// but some of its declarations are using a disabled enum CBPeripheralAuthorizationStatus
-// (disabled using __attribute__ syntax and NS_ENUM_AVAILABLE macro).
-// This + -std=c++11 ends with a compilation error. For the SDK 10.9 we can:
-// 1. either undefine NS_ENUM_AVAILABLE macro (it works somehow) and redefine it as an empty sequence
-// of pp-tokens or
-// 2. define __attribute__ as an empty sequence. Both solutions look quite ugly.
-
-#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) && !QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10)
-
-// Must be included BEFORE CoreBluetooth.h:
-#include <Foundation/Foundation.h>
-
-#define CB_ERROR_WORKAROUND_REQUIRED
-#undef NS_ENUM_AVAILABLE
-#define NS_ENUM_AVAILABLE(_mac, _ios)
-
-#endif // SDK version == 10.9
-
-// In SDK below 10.12 IOBluetooth.h includes CoreBluetooth.h.
+#ifdef Q_OS_MACOS
#include <IOBluetooth/IOBluetooth.h>
+#endif
-#ifdef CB_ERROR_WORKAROUND_REQUIRED
-#undef __attribute__
-#undef CB_ERROR_WORKAROUND_REQUIRED
-#endif // WORKAROUND
-
-#endif // SDK
-
-#endif // QT_OSX_BLUETOOTH
#endif // OSXBLUETOOTH_P_H
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index f7218ca6..70473f1f 100644
--- a/src/bluetooth/osx/osxbtcentralmanager.mm
+++ b/src/bluetooth/osx/osxbtcentralmanager.mm
@@ -48,8 +48,6 @@
#include <algorithm>
#include <limits>
-Q_DECLARE_METATYPE(QLowEnergyCharacteristic)
-Q_DECLARE_METATYPE(QLowEnergyDescriptor)
Q_DECLARE_METATYPE(QLowEnergyHandle)
QT_BEGIN_NAMESPACE
@@ -1032,13 +1030,8 @@ QT_END_NAMESPACE
{
using namespace OSXBluetooth;
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
- const CBManagerState state = central.state;
-#else
- const CBCentralManagerState state = central.state;
-#endif
-
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ 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
|| state == CBManagerStateResetting) {
#else
@@ -1054,7 +1047,7 @@ QT_END_NAMESPACE
}
// Let's check some states we do not like first:
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (state == CBManagerStateUnsupported || state == CBManagerStateUnauthorized) {
#else
if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) {
@@ -1074,7 +1067,7 @@ QT_END_NAMESPACE
return;
}
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (state == CBManagerStatePoweredOff) {
#else
if (state == CBCentralManagerStatePoweredOff) {
@@ -1093,7 +1086,7 @@ QT_END_NAMESPACE
return;
}
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (state == CBManagerStatePoweredOn) {
#else
if (state == CBCentralManagerStatePoweredOn) {
diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm
index 02ec4f90..474fe04b 100644
--- a/src/bluetooth/osx/osxbtl2capchannel.mm
+++ b/src/bluetooth/osx/osxbtl2capchannel.mm
@@ -210,7 +210,7 @@ QT_USE_NAMESPACE
- (BluetoothDeviceAddress)peerAddress
{
const BluetoothDeviceAddress *const addr = device ? [device getAddress]
- : Q_NULLPTR;
+ : nullptr;
if (addr)
return *addr;
@@ -245,7 +245,7 @@ QT_USE_NAMESPACE
Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size");
Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel");
- return [channel writeAsync:data length:length refcon:Q_NULLPTR];
+ return [channel writeAsync:data length:length refcon:nullptr];
}
diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm
index 3ce66d49..7a516dd4 100644
--- a/src/bluetooth/osx/osxbtledeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm
@@ -233,11 +233,10 @@ QT_USE_NAMESPACE
dispatch_queue_t leQueue(qt_LE_queue());
Q_ASSERT(leQueue);
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
- const CBManagerState state(central.state);
+ 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) {
#else
- const CBCentralManagerState state(central.state);
if (state == CBCentralManagerStatePoweredOn) {
#endif
if (internalState == InquiryStarting) {
@@ -260,7 +259,7 @@ QT_USE_NAMESPACE
[manager scanForPeripheralsWithServices:nil options:nil];
} // Else we ignore.
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
} else if (state == CBManagerStateUnsupported || state == CBManagerStateUnauthorized) {
#else
} else if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) {
@@ -277,7 +276,7 @@ QT_USE_NAMESPACE
}
[manager setDelegate:nil];
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
} else if (state == CBManagerStatePoweredOff) {
#else
} else if (state == CBCentralManagerStatePoweredOff) {
diff --git a/src/bluetooth/osx/osxbtobexsession.mm b/src/bluetooth/osx/osxbtobexsession.mm
index b8e604c8..e228d6db 100644
--- a/src/bluetooth/osx/osxbtobexsession.mm
+++ b/src/bluetooth/osx/osxbtobexsession.mm
@@ -489,11 +489,11 @@ QT_USE_NAMESPACE
const OBEXError status = [session OBEXConnect:kOBEXConnectFlagNone
maxPacketLength:[QT_MANGLE_NAMESPACE(OSXBTOBEXSession) maxPacketLength]
- optionalHeaders:Q_NULLPTR
+ optionalHeaders:nullptr
optionalHeadersLength:0
eventSelector:@selector(OBEXConnectHandler:)
selectorTarget:self
- refCon:Q_NULLPTR];
+ refCon:nullptr];
if (status != kOBEXSuccess) {
currentRequest = OSXBluetooth::OBEXNoop;
@@ -572,11 +572,11 @@ QT_USE_NAMESPACE
return kOBEXSessionNotConnectedError;
currentRequest = OBEXAbort;
- const OBEXError status = [session OBEXAbort:Q_NULLPTR
+ const OBEXError status = [session OBEXAbort:nullptr
optionalHeadersLength:0
eventSelector:@selector(OBEXAbortHandler:)
selectorTarget:self
- refCon:Q_NULLPTR];
+ refCon:nullptr];
if (status != kOBEXSuccess)
currentRequest = OBEXNoop;
@@ -677,7 +677,7 @@ QT_USE_NAMESPACE
bodyDataLength:[chunk length]
eventSelector:@selector(OBEXPutHandler:)
selectorTarget:self
- refCon:Q_NULLPTR];
+ refCon:nullptr];
if (status == kOBEXSuccess) {
if (delegate && fileSize && !input->isSequential())
@@ -737,16 +737,16 @@ QT_USE_NAMESPACE
return;
}
- void *dataPtr = chunk ? [chunk mutableBytes] : Q_NULLPTR;
+ void *dataPtr = chunk ? [chunk mutableBytes] : nullptr;
const NSUInteger dataSize = chunk ? [chunk length] : 0;
const OBEXError status = [session OBEXPut:lastChunk
- headersData:Q_NULLPTR
+ headersData:nullptr
headersDataLength:0
bodyData:dataPtr
bodyDataLength:dataSize
eventSelector:@selector(OBEXPutHandler:)
selectorTarget:self
- refCon:Q_NULLPTR];
+ refCon:nullptr];
if (status != kOBEXSuccess) {
qCWarning(QT_BT_OSX) << "failed to send the next memory chunk";
@@ -778,11 +778,11 @@ QT_USE_NAMESPACE
currentRequest = OSXBluetooth::OBEXDisconnect;
- [session OBEXDisconnect:Q_NULLPTR
+ [session OBEXDisconnect:nullptr
optionalHeadersLength:0
eventSelector:@selector(OBEXDisconnectHandler:)
selectorTarget:self
- refCon:Q_NULLPTR];
+ refCon:nullptr];
}
- (void)OBEXDisconnectHandler:(const OBEXSessionEvent*)event
@@ -806,7 +806,7 @@ QT_USE_NAMESPACE
// Clear the delegate and reset the request,
// do not try any of OBEX commands - the session will be deleted
// immediately.
- delegate = Q_NULLPTR;
+ delegate = nullptr;
// This will stop any handler (callback) preventing
// any read/write to potentially deleted objects.
currentRequest = OSXBluetooth::OBEXNoop;
diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm
index 9c443cf6..64c8cd90 100644
--- a/src/bluetooth/osx/osxbtperipheralmanager.mm
+++ b/src/bluetooth/osx/osxbtperipheralmanager.mm
@@ -391,7 +391,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
if (peripheral != manager || !notifier)
return;
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (peripheral.state == CBManagerStatePoweredOn) {
#else
if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
@@ -426,7 +426,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
explicitly added again."
*/
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0) || QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13)
if (peripheral.state == CBManagerStateUnauthorized ||
peripheral.state == CBManagerStateUnsupported) {
#else
diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm
index ea679ec8..bd87aae0 100644
--- a/src/bluetooth/osx/osxbtrfcommchannel.mm
+++ b/src/bluetooth/osx/osxbtrfcommchannel.mm
@@ -210,7 +210,7 @@ QT_USE_NAMESPACE
- (BluetoothDeviceAddress)peerAddress
{
const BluetoothDeviceAddress *const addr = device ? [device getAddress]
- : Q_NULLPTR;
+ : nullptr;
if (addr)
return *addr;
@@ -248,7 +248,7 @@ QT_USE_NAMESPACE
Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size");
Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid RFCOMM channel");
- return [channel writeAsync:data length:length refcon:Q_NULLPTR];
+ return [channel writeAsync:data length:length refcon:nullptr];
}
diff --git a/src/bluetooth/osx/osxbtutility.mm b/src/bluetooth/osx/osxbtutility.mm
index 1508c89f..e17006de 100644
--- a/src/bluetooth/osx/osxbtutility.mm
+++ b/src/bluetooth/osx/osxbtutility.mm
@@ -48,6 +48,7 @@
#ifndef QT_IOS_BLUETOOTH
#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>
+#import <CoreFoundation/CoreFoundation.h>
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12, __IPHONE_NA)
#import <CoreBluetooth/CBUUID.h>
#endif
@@ -164,7 +165,19 @@ QString qt_error_string(IOReturn errorCode)
}
}
-#endif
+void qt_test_iobluetooth_runloop()
+{
+ // IOBluetooth heavily relies on a CFRunLoop machinery in a way it dispatches
+ // its callbacks. Technically, having a QThread with CFRunLoop-based event
+ // dispatcher would suffice. At the moment of writing we do not have such
+ // event dispatcher, so we only can work on the main thread.
+ if (CFRunLoopGetMain() != CFRunLoopGetCurrent()) {
+ qCWarning(QT_BT_OSX) << "IOBluetooth works only on the main thread or a"
+ << "thread with a running CFRunLoop";
+ }
+}
+
+#endif // !QT_IOS_BLUETOOTH
// Apple has: CBUUID, NSUUID, CFUUID, IOBluetoothSDPUUID
diff --git a/src/bluetooth/osx/osxbtutility_p.h b/src/bluetooth/osx/osxbtutility_p.h
index 148ebc0b..c2bc6cf8 100644
--- a/src/bluetooth/osx/osxbtutility_p.h
+++ b/src/bluetooth/osx/osxbtutility_p.h
@@ -82,7 +82,7 @@ public:
// add a default ctor??? This will make the semantics more
// transparent + will simplify the future transition to ARC
// (if it will ever happen).
- explicit ObjCScopedPointer(T *ptr = Q_NULLPTR) : QScopedPointer(ptr){}
+ explicit ObjCScopedPointer(T *ptr = nullptr) : QScopedPointer(ptr){}
operator T*() const
{
return data();
@@ -196,7 +196,7 @@ template<class T>
class CFStrongReference {
public:
CFStrongReference()
- : m_ptr(Q_NULLPTR)
+ : m_ptr(nullptr)
{
}
@@ -230,13 +230,13 @@ public:
CFStrongReference(CFStrongReference &&xval)
{
m_ptr = xval.m_ptr;
- xval.m_ptr = Q_NULLPTR;
+ xval.m_ptr = nullptr;
}
CFStrongReference &operator = (CFStrongReference &&xval)
{
m_ptr = xval.m_ptr;
- xval.m_ptr = Q_NULLPTR;
+ xval.m_ptr = nullptr;
return *this;
}
#endif
@@ -270,7 +270,7 @@ public:
T take()
{
T p = m_ptr;
- m_ptr = Q_NULLPTR;
+ m_ptr = nullptr;
return p;
}
private:
@@ -287,8 +287,9 @@ BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &address);
ObjCStrongReference<IOBluetoothSDPUUID> iobluetooth_uuid(const QBluetoothUuid &uuid);
QBluetoothUuid qt_uuid(IOBluetoothSDPUUID *uuid);
QString qt_error_string(IOReturn errorCode);
+void qt_test_iobluetooth_runloop();
-#endif
+#endif // !QT_IOS_BLUETOOTH
QBluetoothUuid qt_uuid(CBUUID *uuid);
CFStrongReference<CFUUIDRef> cf_uuid(const QBluetoothUuid &qtUuid);
@@ -313,4 +314,23 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_OSX)
QT_END_NAMESPACE
+#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(101300) && QT_MACOS_DEPLOYMENT_TARGET_BELOW(101300)
+
+ // In the macOS 10.13 SDK, the identifier property was moved from the CBPeripheral
+ // and CBCentral classes to a new CBPeer base class. Because CBPeer is only available
+ // on macOS 10.13 and above, the same is true for -[CBPeer identifier]. However,
+ // since we know that the derived classes have always had this property,
+ // we'll explicitly mark its availability here. This will not adversely affect
+ // using the identifier through the CBPeer base class, which will still require macOS 10.13.
+
+@interface CBPeripheral (UnguardedWorkaround)
+@property (readonly, nonatomic) NSUUID *identifier NS_AVAILABLE(10_7, 5_0);
+@end
+
+@interface CBCentral (UnguardedWorkaround)
+@property (readonly, nonatomic) NSUUID *identifier NS_AVAILABLE(10_7, 5_0);
+@end
+
+#endif
+
#endif
diff --git a/src/bluetooth/qbluetooth.h b/src/bluetooth/qbluetooth.h
index 82136eca..df763147 100644
--- a/src/bluetooth/qbluetooth.h
+++ b/src/bluetooth/qbluetooth.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTH_H
#define QBLUETOOTH_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qbluetoothaddress.h b/src/bluetooth/qbluetoothaddress.h
index de2d4240..e3750d21 100644
--- a/src/bluetooth/qbluetoothaddress.h
+++ b/src/bluetooth/qbluetoothaddress.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHADDRESS_H
#define QBLUETOOTHADDRESS_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QByteArray>
#include <QtCore/QString>
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
index b033ae3c..5f142f1a 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
@@ -143,7 +143,15 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
information via \l discoveredDevices() once the discovery has finished. This
will yield the most recent RSSI information.
- \sa QBluetoothDeviceInfo::rssi()
+ If \l lowEnergyDiscoveryTimeout() is larger than 0 the signal is only ever
+ emitted when at least one attribute of \a info changes. This reflects the desire to
+ receive updates as more precise information becomes available. The exception to this
+ behavior is the case when \l lowEnergyDiscoveryTimeout is set to \c 0. A timeout of \c 0
+ expresses the desire to monitor the appearance and disappearance of Low Energy devices
+ over time. Under this condition the \l deviceDiscovered() signal is emitted even if
+ \a info has not changed since the last signal emission.
+
+ \sa QBluetoothDeviceInfo::rssi(), lowEnergyDiscoveryTimeout()
*/
/*!
@@ -325,13 +333,19 @@ void QBluetoothDeviceDiscoveryAgent::start()
}
/*!
- Start Bluetooth device discovery, if it is not already started and the provided
+ Starts Bluetooth device discovery, if it is not already started and the provided
\a methods are supported.
The discovery \a methods limit the scope of the device search.
For example, if the target service or device is a Bluetooth Low Energy device,
this function could be used to limit the search to Bluetooth Low Energy devices and
thereby reduces the discovery time significantly.
+ \note \a methods only determines the type of discovery and does not imply
+ the filtering of the results. For example, the search may still contain classic bluetooth devices
+ despite \a methods being set to \l {QBluetoothDeviceDiscoveryAgent::LowEnergyMethod}
+ {LowEnergyMethod} only. This may happen due to previously cached search results
+ which may be incorporated into the search results.
+
\since 5.8
*/
void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods)
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h
index 8720a125..feb25324 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h
@@ -41,7 +41,7 @@
#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_H
#define QBLUETOOTHDEVICEDISCOVERYAGENT_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QObject>
#include <QtBluetooth/QBluetoothDeviceInfo>
@@ -86,9 +86,9 @@ public:
Q_DECLARE_FLAGS(DiscoveryMethods, DiscoveryMethod)
Q_FLAG(DiscoveryMethods)
- explicit QBluetoothDeviceDiscoveryAgent(QObject *parent = Q_NULLPTR);
+ explicit QBluetoothDeviceDiscoveryAgent(QObject *parent = nullptr);
explicit QBluetoothDeviceDiscoveryAgent(const QBluetoothAddress &deviceAdapter,
- QObject *parent = Q_NULLPTR);
+ QObject *parent = nullptr);
~QBluetoothDeviceDiscoveryAgent();
// TODO Remove inquiry type in Qt 6 -> not really used anywhere
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index e76ddff7..303dd67f 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -165,7 +165,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
{
qCWarning(QT_BT_ANDROID) << "Search not possible due to missing permission (ACCESS_COARSE_LOCATION)";
lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
- errorString = QBluetoothDeviceDiscoveryAgent::tr("Missing Location permission. Search is not possible");
+ errorString = QBluetoothDeviceDiscoveryAgent::tr("Missing Location permission. Search is not possible.");
emit q->error(lastError);
return;
}
@@ -225,6 +225,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
return;
if (m_active == SDPScanActive) {
+ if (pendingCancel)
+ return;
+
pendingCancel = true;
pendingStart = false;
bool success = adapter.callMethod<jboolean>("cancelDiscovery");
@@ -304,7 +307,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices(
for (int i = 0; i < discoveredDevices.size(); i++) {
if (discoveredDevices[i].address() == info.address()) {
- if (discoveredDevices[i] == info) {
+ if (discoveredDevices[i] == info && lowEnergySearchTimeout > 0) {
qCDebug(QT_BT_ANDROID) << "Duplicate: " << info.address()
<< "isLeScanResult:" << isLeResult;
return;
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
index 5288eaf8..3cc3354a 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
@@ -51,6 +51,7 @@
#include "bluez/adapter1_bluez5_p.h"
#include "bluez/device1_bluez5_p.h"
#include "bluez/properties_p.h"
+#include "bluez/bluetoothmanagement_p.h"
QT_BEGIN_NAMESPACE
@@ -82,6 +83,8 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
SIGNAL(InterfacesAdded(QDBusObjectPath,InterfaceList)),
q, SLOT(_q_InterfacesAdded(QDBusObjectPath,InterfaceList)));
+ // start private address monitoring
+ BluetoothManagement::instance();
} else {
manager = new OrgBluezManagerInterface(QStringLiteral("org.bluez"), QStringLiteral("/"),
QDBusConnection::systemBus(), parent);
@@ -122,7 +125,7 @@ QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent:
return (ClassicMethod | LowEnergyMethod);
}
-void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods /*methods*/)
+void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
{
// Currently both BlueZ backends do not distinguish discovery methods.
// The DBus API's always return both device types. Therefore we ignore
@@ -136,7 +139,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
discoveredDevices.clear();
if (managerBluez5) {
- startBluez5();
+ startBluez5(methods);
return;
}
@@ -225,11 +228,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
}
}
-void QBluetoothDeviceDiscoveryAgentPrivate::startBluez5()
+void QBluetoothDeviceDiscoveryAgentPrivate::startBluez5(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
-
bool ok = false;
const QString adapterPath = findAdapterForAddress(m_adapterAddress, &ok);
if (!ok || adapterPath.isEmpty()) {
@@ -254,6 +256,33 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startBluez5()
return;
}
+ QVariantMap map;
+ if (methods == (QBluetoothDeviceDiscoveryAgent::LowEnergyMethod|QBluetoothDeviceDiscoveryAgent::ClassicMethod))
+ map.insert(QStringLiteral("Transport"), QStringLiteral("auto"));
+ else if (methods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)
+ map.insert(QStringLiteral("Transport"), QStringLiteral("le"));
+ else
+ map.insert(QStringLiteral("Transport"), QStringLiteral("bredr"));
+
+ // older BlueZ 5.x versions don't have this function
+ // filterReply returns UnknownMethod which we ignore
+ QDBusPendingReply<> filterReply = adapterBluez5->SetDiscoveryFilter(map);
+ filterReply.waitForFinished();
+ if (filterReply.isError()) {
+ if (filterReply.error().type() == QDBusError::Other
+ && filterReply.error().name() == QStringLiteral("org.bluez.Error.Failed")) {
+ qCDebug(QT_BT_BLUEZ) << "Discovery method" << methods << "not supported";
+ lastError = QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod;
+ errorString = QBluetoothDeviceDiscoveryAgent::tr("One or more device discovery methods "
+ "are not supported on this platform");
+ delete adapterBluez5;
+ adapterBluez5 = 0;
+ emit q->error(lastError);
+ return;
+ } else if (filterReply.error().type() != QDBusError::UnknownMethod) {
+ qCDebug(QT_BT_BLUEZ) << "SetDiscoveryFilter failed:" << filterReply.error();
+ }
+ }
QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapterBluez5->path());
QObject::connect(QtBluezDiscoveryManager::instance(), SIGNAL(discoveryInterrupted(QString)),
@@ -400,21 +429,37 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFoundBluez5(const QString& dev
// read information
QBluetoothDeviceInfo deviceInfo(btAddress, btName, btClass);
-
- if (!btClass)
- deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
- else
- deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
-
deviceInfo.setRssi(device.rSSI());
+
QList<QBluetoothUuid> uuids;
- foreach (const QString &u, device.uUIDs())
- uuids.append(QBluetoothUuid(u));
+ bool foundLikelyLowEnergyUuid = false;
+ for (const auto &u: device.uUIDs()) {
+ const QBluetoothUuid id(u);
+ if (id.isNull())
+ continue;
+
+ if (!foundLikelyLowEnergyUuid) {
+ //once we found one BTLE service we are done
+ bool ok = false;
+ quint16 shortId = id.toUInt16(&ok);
+ if (ok && ((shortId & QBluetoothUuid::GenericAccess) == QBluetoothUuid::GenericAccess))
+ foundLikelyLowEnergyUuid = true;
+ }
+ uuids.append(id);
+ }
deviceInfo.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ if (!btClass) {
+ deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
+ } else {
+ deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
+ if (foundLikelyLowEnergyUuid)
+ deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration);
+ }
+
for (int i = 0; i < discoveredDevices.size(); i++) {
if (discoveredDevices[i].address() == deviceInfo.address()) {
- if (discoveredDevices[i] == deviceInfo) {
+ if (discoveredDevices[i] == deviceInfo && lowEnergySearchTimeout > 0) {
qCDebug(QT_BT_BLUEZ) << "Duplicate: " << btAddress.toString();
return;
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
index 3f4c6755..c50d546d 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
@@ -127,7 +127,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(con
Q_UNUSED(adapter);
registerQDeviceDiscoveryMetaType();
- Q_ASSERT_X(q != Q_NULLPTR, Q_FUNC_INFO, "invalid q_ptr (null)");
+ Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
}
QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm
index b308f7cc..fed33bb2 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm
@@ -90,7 +90,7 @@ public:
QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress & address,
QBluetoothDeviceDiscoveryAgent *q);
- ~QBluetoothDeviceDiscoveryAgentPrivate() Q_DECL_OVERRIDE;
+ ~QBluetoothDeviceDiscoveryAgentPrivate() override;
bool isValid() const;
bool isActive() const;
@@ -108,9 +108,9 @@ private:
};
// DeviceInquiryDelegate:
- void inquiryFinished(IOBluetoothDeviceInquiry *inq) Q_DECL_OVERRIDE;
- void error(IOBluetoothDeviceInquiry *inq, IOReturn error) Q_DECL_OVERRIDE;
- void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) Q_DECL_OVERRIDE;
+ void inquiryFinished(IOBluetoothDeviceInquiry *inq) override;
+ void error(IOBluetoothDeviceInquiry *inq, IOReturn error) override;
+ void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) override;
void LEinquiryFinished();
void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
@@ -168,7 +168,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(con
{
registerQDeviceDiscoveryMetaType();
- Q_ASSERT_X(q != Q_NULLPTR, Q_FUNC_INFO, "invalid q_ptr (null)");
+ Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
HostController controller([[IOBluetoothHostController defaultController] retain]);
if (!controller || [controller powerState] != kBluetoothHCIPowerStateON) {
@@ -245,6 +245,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod);
Q_ASSERT(agentState == NonActive);
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
if (!inquiry) {
// The first Classic scan for this DDA.
inquiry.reset([[DeviceInquiryObjC alloc]initWithDelegate:this]);
@@ -525,7 +527,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
for (int i = 0, e = discoveredDevices.size(); i < e; ++i) {
if (isLE ? discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid():
discoveredDevices[i].address() == newDeviceInfo.address()) {
- if (discoveredDevices[i] == newDeviceInfo)
+ if (discoveredDevices[i] == newDeviceInfo && (!isLE || lowEnergySearchTimeout > 0))
return;
discoveredDevices.replace(i, newDeviceInfo);
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index 9eadfae4..a1135bf1 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -83,12 +83,12 @@ QT_END_NAMESPACE
#include <QtConcurrent>
#endif
+QT_BEGIN_NAMESPACE
+
#ifdef QT_WINRT_BLUETOOTH
class QWinRTBluetoothDeviceDiscoveryWorker;
#endif
-QT_BEGIN_NAMESPACE
-
class QBluetoothDeviceDiscoveryAgentPrivate
#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_WIN_BLUETOOTH)
: public QObject
@@ -158,7 +158,7 @@ private:
QList<OrgFreedesktopDBusPropertiesInterface *> propertyMonitors;
void deviceFoundBluez5(const QString& devicePath);
- void startBluez5();
+ void startBluez5(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
bool useExtendedDiscovery;
QTimer extendedDiscoveryTimer;
@@ -193,7 +193,6 @@ private:
private slots:
void registerDevice(const QBluetoothDeviceInfo &info);
void onScanFinished();
- void onScanCanceled();
private:
void disconnectAndClearWorker();
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index d8d68d4b..6786ac54 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -41,6 +41,10 @@
#include "qbluetoothdevicediscoveryagent_p.h"
#include "qbluetoothaddress.h"
#include "qbluetoothuuid.h"
+
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include "qfunctions_winrt.h"
#include <QtCore/QLoggingCategory>
@@ -104,12 +108,11 @@ private:
HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck = CheckForPairing);
public slots:
- void handleLeTimeout();
+ void finishDiscovery();
Q_SIGNALS:
void deviceFound(const QBluetoothDeviceInfo &info);
void scanFinished();
- void scanCanceled();
public:
quint8 requestedModes;
@@ -130,6 +133,9 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
{
qRegisterMetaType<QBluetoothDeviceInfo>();
+#ifdef CLASSIC_APP_BUILD
+ CoInitialize(NULL);
+#endif
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothDevice).Get(), &m_deviceStatics);
Q_ASSERT_SUCCEEDED(hr);
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(), &m_leDeviceStatics);
@@ -139,6 +145,9 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker()
{
stop();
+#ifdef CLASSIC_APP_BUILD
+ CoUninitialize();
+#endif
}
void QWinRTBluetoothDeviceDiscoveryWorker::start()
@@ -248,12 +257,9 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
Q_ASSERT_SUCCEEDED(hr);
}
-void QWinRTBluetoothDeviceDiscoveryWorker::handleLeTimeout()
+void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery()
{
- if (m_pendingPairedDevices == 0)
- emit scanFinished();
- else
- emit scanCanceled();
+ emit scanFinished();
deleteLater();
}
@@ -267,6 +273,9 @@ void QWinRTBluetoothDeviceDiscoveryWorker::classicBluetoothInfoFromDeviceIdAsync
HRESULT hr = m_deviceStatics->FromIdAsync(deviceId, &deviceFromIdOperation);
if (FAILED(hr)) {
--m_pendingPairedDevices;
+ if (!m_pendingPairedDevices
+ && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod))
+ finishDiscovery();
qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from id";
return S_OK;
}
@@ -275,6 +284,9 @@ void QWinRTBluetoothDeviceDiscoveryWorker::classicBluetoothInfoFromDeviceIdAsync
(this, &QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoundAsync).Get());
if (FAILED(hr)) {
--m_pendingPairedDevices;
+ if (!m_pendingPairedDevices
+ && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod))
+ finishDiscovery();
qCWarning(QT_BT_WINRT) << "Could not register device found callback";
return S_OK;
}
@@ -390,6 +402,8 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
Q_ARG(QBluetoothDeviceInfo, info));
+ if (!m_pendingPairedDevices && !(requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod))
+ finishDiscovery();
return S_OK;
}
@@ -552,8 +566,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
- connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanCanceled,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanCanceled);
worker->start();
if (lowEnergySearchTimeout > 0 && methods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { // otherwise no timeout and stop() required
@@ -562,7 +574,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
leScanTimer->setSingleShot(true);
}
connect(leScanTimer, &QTimer::timeout,
- worker, &QWinRTBluetoothDeviceDiscoveryWorker::handleLeTimeout);
+ worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
leScanTimer->setInterval(lowEnergySearchTimeout);
leScanTimer->start();
}
@@ -613,28 +625,19 @@ void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
emit q->finished();
}
-void QBluetoothDeviceDiscoveryAgentPrivate::onScanCanceled()
-{
- Q_Q(QBluetoothDeviceDiscoveryAgent);
- disconnectAndClearWorker();
- emit q->canceled();
-}
-
void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
if (!worker)
return;
- disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanCanceled,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanCanceled);
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered);
if (leScanTimer) {
disconnect(leScanTimer, &QTimer::timeout,
- worker, &QWinRTBluetoothDeviceDiscoveryWorker::handleLeTimeout);
+ worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
}
worker.clear();
}
diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h
index 751c8384..f2558bbf 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.h
+++ b/src/bluetooth/qbluetoothdeviceinfo.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHDEVICEINFO_H
#define QBLUETOOTHDEVICEINFO_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qmetatype.h>
@@ -189,6 +189,7 @@ public:
};
Q_DECLARE_FLAGS(ServiceClasses, ServiceClass)
+ //TODO Qt6 Remove DataCompleteness -> it serves no purpose
enum DataCompleteness {
DataComplete,
DataIncomplete,
@@ -231,7 +232,7 @@ public:
void setRssi(qint16 signal);
void setServiceUuids(const QList<QBluetoothUuid> &uuids, DataCompleteness completeness);
- QList<QBluetoothUuid> serviceUuids(DataCompleteness *completeness = Q_NULLPTR) const;
+ QList<QBluetoothUuid> serviceUuids(DataCompleteness *completeness = nullptr) const;
DataCompleteness serviceUuidsCompleteness() const;
void setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs);
diff --git a/src/bluetooth/qbluetoothhostinfo.h b/src/bluetooth/qbluetoothhostinfo.h
index e92bdb5c..42dfcaab 100644
--- a/src/bluetooth/qbluetoothhostinfo.h
+++ b/src/bluetooth/qbluetoothhostinfo.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHHOSTINFO_H
#define QBLUETOOTHHOSTINFO_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/QBluetoothAddress>
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qbluetoothlocaldevice.h b/src/bluetooth/qbluetoothlocaldevice.h
index 49de25ae..9f6d1e1b 100644
--- a/src/bluetooth/qbluetoothlocaldevice.h
+++ b/src/bluetooth/qbluetoothlocaldevice.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHLOCALDEVICE_H
#define QBLUETOOTHLOCALDEVICE_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QObject>
#include <QtCore/QList>
@@ -79,8 +79,8 @@ public:
};
Q_ENUM(Error)
- explicit QBluetoothLocalDevice(QObject *parent = Q_NULLPTR);
- explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = Q_NULLPTR);
+ explicit QBluetoothLocalDevice(QObject *parent = nullptr);
+ explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = nullptr);
virtual ~QBluetoothLocalDevice();
bool isValid() const;
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index c8c5ffbf..0982573e 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include <QtCore/QLoggingCategory>
+#include <QtCore/QRandomGenerator>
#include <QtDBus/QDBusContext>
#include "qbluetoothlocaldevice.h"
@@ -798,9 +799,8 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
connect(adapter, SIGNAL(PropertyChanged(QString, QDBusVariant)),
SLOT(PropertyChanged(QString, QDBusVariant)));
- qsrand(QTime::currentTime().msec());
agent_path = agentPath;
- agent_path.append(QString::fromLatin1("/%1").arg(qrand()));
+ agent_path.append(QString::fromLatin1("/%1").arg(QRandomGenerator::get32()));
}
}
@@ -1164,7 +1164,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(qrand() % 1000000);
+ QString pin = QString::fromLatin1("%1").arg(QRandomGenerator::bounded(1000000));
pin = QString::fromLatin1("%1").arg(pin, 6, QLatin1Char('0'));
emit q->pairingDisplayPinCode(address, pin);
@@ -1276,7 +1276,7 @@ uint QBluetoothLocalDevicePrivate::RequestPasskey(const QDBusObjectPath &in0)
{
Q_UNUSED(in0);
qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
- return (qrand() % 1000000);
+ return (QRandomGenerator::bounded(1000000));
}
// Bluez 4
diff --git a/src/bluetooth/qbluetoothlocaldevice_osx.mm b/src/bluetooth/qbluetoothlocaldevice_osx.mm
index 45fa310a..52b7bba8 100644
--- a/src/bluetooth/qbluetoothlocaldevice_osx.mm
+++ b/src/bluetooth/qbluetoothlocaldevice_osx.mm
@@ -74,18 +74,18 @@ public:
private:
// PairingDelegate:
- void connecting(ObjCPairingRequest *pair) Q_DECL_OVERRIDE;
- void requestPIN(ObjCPairingRequest *pair) Q_DECL_OVERRIDE;
+ void connecting(ObjCPairingRequest *pair) override;
+ void requestPIN(ObjCPairingRequest *pair) override;
void requestUserConfirmation(ObjCPairingRequest *pair,
- BluetoothNumericValue) Q_DECL_OVERRIDE;
+ BluetoothNumericValue) override;
void passkeyNotification(ObjCPairingRequest *pair,
- BluetoothPasskey passkey) Q_DECL_OVERRIDE;
- void error(ObjCPairingRequest *pair, IOReturn errorCode) Q_DECL_OVERRIDE;
- void pairingFinished(ObjCPairingRequest *pair) Q_DECL_OVERRIDE;
+ BluetoothPasskey passkey) override;
+ void error(ObjCPairingRequest *pair, IOReturn errorCode) override;
+ void pairingFinished(ObjCPairingRequest *pair) override;
// ConnectionMonitor
- void deviceConnected(const QBluetoothAddress &deviceAddress) Q_DECL_OVERRIDE;
- void deviceDisconnected(const QBluetoothAddress &deviceAddress) Q_DECL_OVERRIDE;
+ void deviceConnected(const QBluetoothAddress &deviceAddress) override;
+ void deviceDisconnected(const QBluetoothAddress &deviceAddress) override;
void emitPairingFinished(const QBluetoothAddress &deviceAddress, Pairing pairing, bool queued);
void emitError(QBluetoothLocalDevice::Error error, bool queued);
@@ -464,6 +464,8 @@ void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pai
return;
}
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
return d_ptr->requestPairing(address, pairing);
}
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index 3e169837..d0db3a1f 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -52,7 +52,7 @@
// We mean it.
//
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include "qbluetoothlocaldevice.h"
diff --git a/src/bluetooth/qbluetoothserver.h b/src/bluetooth/qbluetoothserver.h
index 568ca3d9..193101fc 100644
--- a/src/bluetooth/qbluetoothserver.h
+++ b/src/bluetooth/qbluetoothserver.h
@@ -41,7 +41,7 @@
#ifndef QBLUETOOTHSERVER_H
#define QBLUETOOTHSERVER_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QObject>
@@ -70,7 +70,7 @@ public:
};
Q_ENUM(Error)
- explicit QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = Q_NULLPTR);
+ explicit QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = nullptr);
~QBluetoothServer();
void close();
diff --git a/src/bluetooth/qbluetoothserver_osx.mm b/src/bluetooth/qbluetoothserver_osx.mm
index 8896651d..a1774d14 100644
--- a/src/bluetooth/qbluetoothserver_osx.mm
+++ b/src/bluetooth/qbluetoothserver_osx.mm
@@ -237,7 +237,7 @@ QBluetoothServerPrivate *QBluetoothServerPrivate::registeredServer(quint16 port,
qCWarning(QT_BT_OSX) << "invalid protocol";
}
- return Q_NULLPTR;
+ return nullptr;
}
void QBluetoothServerPrivate::unregisterServer(QBluetoothServerPrivate *server)
@@ -291,6 +291,8 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
{
typedef QBluetoothServerPrivate::ObjCListener ObjCListener;
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
if (d_ptr->listener) {
qCWarning(QT_BT_OSX) << "already in listen mode, close server first";
return false;
@@ -441,7 +443,7 @@ bool QBluetoothServer::hasPendingConnections() const
QBluetoothSocket *QBluetoothServer::nextPendingConnection()
{
if (!d_ptr->pendingConnections.size())
- return Q_NULLPTR;
+ return nullptr;
QScopedPointer<QBluetoothSocket> newSocket(new QBluetoothSocket);
QBluetoothServerPrivate::PendingConnection channel(d_ptr->pendingConnections.front());
@@ -451,10 +453,10 @@ QBluetoothSocket *QBluetoothServer::nextPendingConnection()
if (d_ptr->serverType == QSInfo::RfcommProtocol) {
if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothRFCOMMChannel *>(channel)))
- return Q_NULLPTR;
+ return nullptr;
} else {
if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothL2CAPChannel *>(channel)))
- return Q_NULLPTR;
+ return nullptr;
}
return newSocket.take();
diff --git a/src/bluetooth/qbluetoothserver_osx_p.h b/src/bluetooth/qbluetoothserver_osx_p.h
index 63d0f314..3116ca02 100644
--- a/src/bluetooth/qbluetoothserver_osx_p.h
+++ b/src/bluetooth/qbluetoothserver_osx_p.h
@@ -80,8 +80,8 @@ private:
void stopListener();
// SocketListener (delegate):
- void openNotify(IOBluetoothRFCOMMChannel *channel) Q_DECL_OVERRIDE;
- void openNotify(IOBluetoothL2CAPChannel *channel) Q_DECL_OVERRIDE;
+ void openNotify(IOBluetoothRFCOMMChannel *channel) override;
+ void openNotify(IOBluetoothL2CAPChannel *channel) override;
QBluetoothServiceInfo::Protocol serverType;
QBluetoothServer *q_ptr;
diff --git a/src/bluetooth/qbluetoothserver_winrt.cpp b/src/bluetooth/qbluetoothserver_winrt.cpp
index 61134c1f..08aa45b4 100644
--- a/src/bluetooth/qbluetoothserver_winrt.cpp
+++ b/src/bluetooth/qbluetoothserver_winrt.cpp
@@ -44,6 +44,9 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include <qfunctions_winrt.h>
#include <windows.networking.h>
@@ -70,6 +73,9 @@ QHash<QBluetoothServerPrivate *, int> __fakeServerPorts;
QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType)
: maxPendingConnections(1), serverType(sType), m_lastError(QBluetoothServer::NoError), socket(0)
{
+#ifdef CLASSIC_APP_BUILD
+ CoInitialize(NULL);
+#endif
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
}
@@ -79,6 +85,12 @@ QBluetoothServerPrivate::~QBluetoothServerPrivate()
__fakeServerPorts.remove(this);
if (socket)
delete socket;
+#ifdef CLASSIC_APP_BUILD
+ // If we do not reset that pointer, socketListener will go out of scope after CoUninitialize was
+ // called, which will lead to a crash.
+ socketListener = nullptr;
+ CoUninitialize();
+#endif
}
bool QBluetoothServerPrivate::isListening() const
@@ -217,6 +229,8 @@ bool QBluetoothServer::hasPendingConnections() const
QBluetoothSocket *QBluetoothServer::nextPendingConnection()
{
Q_D(QBluetoothServer);
+ if (d->pendingConnections.count() == 0)
+ return nullptr;
ComPtr<IStreamSocket> socket = d->pendingConnections.takeFirst();
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
index 8998d608..d6163f0e 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
@@ -442,7 +442,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery()
setDiscoveryState(DeviceDiscovery);
- deviceDiscoveryAgent->start();
+ deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
}
/*!
@@ -450,6 +450,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery()
*/
void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery()
{
+ // disconnect to avoid recursion during stop() - QTBUG-60131
+ // we don't care about a potential signals from device discovery agent anymore
+ deviceDiscoveryAgent->disconnect();
+
deviceDiscoveryAgent->stop();
delete deviceDiscoveryAgent;
deviceDiscoveryAgent = 0;
@@ -497,6 +501,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothD
error = static_cast<QBluetoothServiceDiscoveryAgent::Error>(newError);
errorString = deviceDiscoveryAgent->errorString();
+ // disconnect to avoid recursion during stop() - QTBUG-60131
+ // we don't care about a potential signals from device discovery agent anymore
+ deviceDiscoveryAgent->disconnect();
+
deviceDiscoveryAgent->stop();
delete deviceDiscoveryAgent;
deviceDiscoveryAgent = 0;
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h
index 246de953..4b1a72c1 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_H
#define QBLUETOOTHSERVICEDISCOVERYAGENT_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QObject>
@@ -80,8 +80,8 @@ public:
};
Q_ENUM(DiscoveryMode)
- explicit QBluetoothServiceDiscoveryAgent(QObject *parent = Q_NULLPTR);
- explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = Q_NULLPTR);
+ explicit QBluetoothServiceDiscoveryAgent(QObject *parent = nullptr);
+ explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = nullptr);
~QBluetoothServiceDiscoveryAgent();
bool isActive() const;
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index ba5bcb0a..51db091e 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -244,6 +244,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_processFetchedUuids(
//could not find any service for the current address/device -> go to next one
if (address.isNull() || uuids.isEmpty()) {
+ if (discoveredDevices.count() == 1) {
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+ QTimer::singleShot(4000, q, SLOT(_q_fetchUuidsTimeout()));
+ }
_q_serviceDiscoveryFinished();
return;
}
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
index 4a52b379..1d0cc7da 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
@@ -88,8 +88,8 @@ public:
private:
// SDPInquiryDelegate:
- void SDPInquiryFinished(IOBluetoothDevice *device) Q_DECL_OVERRIDE;
- void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) Q_DECL_OVERRIDE;
+ void SDPInquiryFinished(IOBluetoothDevice *device) override;
+ void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) override;
void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
void setupDeviceDiscoveryAgent();
@@ -141,7 +141,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery()
state = DeviceDiscovery;
setupDeviceDiscoveryAgent();
- deviceDiscoveryAgent->start();
+ deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
}
void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery()
@@ -152,7 +152,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery()
Q_ASSERT_X(state == DeviceDiscovery, Q_FUNC_INFO, "invalid state");
deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(Q_NULLPTR);
+ deviceDiscoveryAgent.reset(nullptr);
state = Inactive;
emit q_ptr->canceled();
@@ -268,7 +268,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothD
errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(Q_NULLPTR);
+ deviceDiscoveryAgent.reset(nullptr);
state = QBluetoothServiceDiscoveryAgentPrivate::Inactive;
emit q_ptr->error(error);
@@ -283,12 +283,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished()
//Forward the device discovery error
error = static_cast<QBluetoothServiceDiscoveryAgent::Error>(deviceDiscoveryAgent->error());
errorString = deviceDiscoveryAgent->errorString();
- deviceDiscoveryAgent.reset(Q_NULLPTR);
+ deviceDiscoveryAgent.reset(nullptr);
state = Inactive;
emit q_ptr->error(error);
emit q_ptr->finished();
} else {
- deviceDiscoveryAgent.reset(Q_NULLPTR);
+ deviceDiscoveryAgent.reset(nullptr);
startServiceDiscovery();
}
}
@@ -526,6 +526,8 @@ QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const
void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode)
{
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
if (d_ptr->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive
&& d_ptr->error != InvalidBluetoothAdapterError)
{
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
index fe8f635a..956ccabb 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
@@ -76,10 +76,6 @@ QT_END_NAMESPACE
#include <QFutureWatcher>
#endif
-#ifdef QT_WINRT_BLUETOOTH
-class QWinRTBluetoothServiceDiscoveryWorker;
-#endif
-
QT_BEGIN_NAMESPACE
class QBluetoothDeviceDiscoveryAgent;
@@ -90,6 +86,10 @@ class LocalDeviceBroadcastReceiver;
#include <QtBluetooth/QBluetoothLocalDevice>
#endif
+#ifdef QT_WINRT_BLUETOOTH
+class QWinRTBluetoothServiceDiscoveryWorker;
+#endif
+
class QBluetoothServiceDiscoveryAgentPrivate
#if defined QT_WINRT_BLUETOOTH
: public QObject
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
index 29ccb290..77310d01 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
@@ -40,6 +40,9 @@
#include "qbluetoothservicediscoveryagent.h"
#include "qbluetoothservicediscoveryagent_p.h"
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include <qfunctions_winrt.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp
index d2920d78..e4e5d1ed 100644
--- a/src/bluetooth/qbluetoothserviceinfo.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo.cpp
@@ -342,7 +342,7 @@ bool QBluetoothServiceInfo::unregisterService()
Construct a new invalid QBluetoothServiceInfo;
*/
QBluetoothServiceInfo::QBluetoothServiceInfo()
- : d_ptr(QSharedPointer<QBluetoothServiceInfoPrivate>(new QBluetoothServiceInfoPrivate))
+ : d_ptr(QSharedPointer<QBluetoothServiceInfoPrivate>::create())
{
}
diff --git a/src/bluetooth/qbluetoothserviceinfo.h b/src/bluetooth/qbluetoothserviceinfo.h
index 38cddfb6..cc4041e2 100644
--- a/src/bluetooth/qbluetoothserviceinfo.h
+++ b/src/bluetooth/qbluetoothserviceinfo.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHSERVICEINFO_H
#define QBLUETOOTHSERVICEINFO_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/QBluetoothUuid>
#include <QtBluetooth/QBluetoothAddress>
diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm
index a25653ab..6da9d7a2 100644
--- a/src/bluetooth/qbluetoothserviceinfo_osx.mm
+++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm
@@ -127,7 +127,7 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca
const QSInfo::Protocol type = q_ptr->socketProtocol();
quint16 realPort = 0;
- QBluetoothServerPrivate *server = Q_NULLPTR;
+ QBluetoothServerPrivate *server = nullptr;
bool configured = false;
if (type == QBluetoothServiceInfo::L2capProtocol) {
@@ -179,7 +179,7 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
serviceRecord.reset(nil);
const QSInfo::Protocol type = q_ptr->socketProtocol();
- QBluetoothServerPrivate *server = Q_NULLPTR;
+ QBluetoothServerPrivate *server = nullptr;
const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex());
if (type == QSInfo::RfcommProtocol)
diff --git a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
index d72056b7..975a3f4a 100644
--- a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
@@ -42,6 +42,9 @@
#include "qbluetoothserver_p.h"
#include <QtCore/QLoggingCategory>
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include <qfunctions_winrt.h>
#include <wrl.h>
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index 3e961142..a35863b4 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -112,6 +112,8 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
supported on this platform.
\value OperationError An operation was attempted while the socket was in a state
that did not permit it.
+ \value RemoteHostClosedError The remote host closed the connection. This value was
+ introduced by Qt 5.10.
*/
/*!
@@ -300,7 +302,7 @@ qint64 QBluetoothSocket::bytesAvailable() const
qint64 QBluetoothSocket::bytesToWrite() const
{
Q_D(const QBluetoothSocket);
- return d->txBuffer.size();
+ return d->bytesToWrite();
}
/*!
@@ -624,7 +626,7 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
bool QBluetoothSocket::canReadLine() const
{
Q_D(const QBluetoothSocket);
- return d->buffer.canReadLine() || QIODevice::canReadLine();
+ return d->canReadLine();
}
/*!
@@ -854,12 +856,18 @@ QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error)
case QBluetoothSocket::HostNotFoundError:
debug << "QBluetoothSocket::HostNotFoundError";
break;
+ case QBluetoothSocket::RemoteHostClosedError:
+ debug << "QBluetoothSocket::RemoteHostClosedError";
+ break;
case QBluetoothSocket::ServiceNotFoundError:
debug << "QBluetoothSocket::ServiceNotFoundError";
break;
case QBluetoothSocket::NetworkError:
debug << "QBluetoothSocket::NetworkError";
break;
+ case QBluetoothSocket::UnsupportedProtocolError:
+ debug << "QBluetoothSocket::UnsupportedProtocolError";
+ break;
default:
debug << "QBluetoothSocket::SocketError(" << (int)error << ")";
}
diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h
index 97b6685b..3fc2892e 100644
--- a/src/bluetooth/qbluetoothsocket.h
+++ b/src/bluetooth/qbluetoothsocket.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHSOCKET_H
#define QBLUETOOTHSOCKET_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/qbluetooth.h>
#include <QtBluetooth/qbluetoothaddress.h>
@@ -79,6 +79,7 @@ public:
enum SocketError {
NoSocketError = -2,
UnknownSocketError = QAbstractSocket::UnknownSocketError, //-1
+ RemoteHostClosedError = QAbstractSocket::RemoteHostClosedError, //1
HostNotFoundError = QAbstractSocket::HostNotFoundError, //2
ServiceNotFoundError = QAbstractSocket::SocketAddressNotAvailableError, //9
NetworkError = QAbstractSocket::NetworkError, //7
@@ -88,8 +89,8 @@ public:
};
Q_ENUM(SocketError)
- explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = Q_NULLPTR); // create socket of type socketType
- explicit QBluetoothSocket(QObject *parent = Q_NULLPTR); // create a blank socket
+ explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = nullptr); // create socket of type socketType
+ explicit QBluetoothSocket(QObject *parent = nullptr); // create a blank socket
virtual ~QBluetoothSocket();
void abort();
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index 56d4f77b..d0b901ae 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -46,6 +46,7 @@
#include <QtCore/QTime>
#include <QtCore/private/qjni_p.h>
#include <QtAndroidExtras/QAndroidJniEnvironment>
+#include <QtAndroid>
QT_BEGIN_NAMESPACE
@@ -56,6 +57,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
Q_DECLARE_METATYPE(QAndroidJniObject)
+Q_BLUETOOTH_EXPORT bool useReverseUuidWorkAroundConnect = true;
/* BluetoothSocket.connect() can block up to 10s. Therefore it must be
* in a separate thread. Unfortunately if BluetoothSocket.close() is
@@ -78,10 +80,12 @@ class SocketConnectWorker : public QObject
Q_OBJECT
public:
SocketConnectWorker(const QAndroidJniObject& socket,
- const QAndroidJniObject& targetUuid)
+ const QAndroidJniObject& targetUuid,
+ const QBluetoothUuid& qtTargetUuid)
: QObject(),
mSocketObject(socket),
- mTargetUuid(targetUuid)
+ mTargetUuid(targetUuid),
+ mQtTargetUuid(qtTargetUuid)
{
static int t = qRegisterMetaType<QAndroidJniObject>();
Q_UNUSED(t);
@@ -90,7 +94,8 @@ public:
signals:
void socketConnectDone(const QAndroidJniObject &socket);
void socketConnectFailed(const QAndroidJniObject &socket,
- const QAndroidJniObject &targetUuid);
+ const QAndroidJniObject &targetUuid,
+ const QBluetoothUuid &qtUuid);
public slots:
void connectSocket()
{
@@ -102,7 +107,7 @@ public slots:
env->ExceptionDescribe();
env->ExceptionClear();
- emit socketConnectFailed(mSocketObject, mTargetUuid);
+ emit socketConnectFailed(mSocketObject, mTargetUuid, mQtTargetUuid);
QThread::currentThread()->quit();
return;
}
@@ -130,6 +135,8 @@ public slots:
private:
QAndroidJniObject mSocketObject;
QAndroidJniObject mTargetUuid;
+ // same as mTargetUuid above - just the Qt C++ version rather than jni uuid
+ QBluetoothUuid mQtTargetUuid;
};
class WorkerThread: public QThread
@@ -143,10 +150,11 @@ public:
// Runs in same thread as QBluetoothSocketPrivate
void setupWorker(QBluetoothSocketPrivate* d_ptr, const QAndroidJniObject& socketObject,
- const QAndroidJniObject& uuidObject, bool useFallback)
+ const QAndroidJniObject& uuidObject, bool useFallback,
+ const QBluetoothUuid& qtUuid = QBluetoothUuid())
{
SocketConnectWorker* worker = new SocketConnectWorker(
- socketObject, uuidObject);
+ socketObject, uuidObject, qtUuid);
worker->moveToThread(this);
connect(this, &QThread::finished, worker, &QObject::deleteLater);
@@ -172,6 +180,30 @@ private:
QPointer<SocketConnectWorker> workerPointer;
};
+/*
+ * This function is part of a workaround for QTBUG-61392
+ *
+ * Returns null uuid if the given \a serviceUuid is not a uuid
+ * derived from the Bluetooth base uuid.
+ */
+static QBluetoothUuid reverseUuid(const QBluetoothUuid &serviceUuid)
+{
+ if (serviceUuid.isNull())
+ return QBluetoothUuid();
+
+ bool isBaseUuid = false;
+ serviceUuid.toUInt32(&isBaseUuid);
+ if (isBaseUuid)
+ return QBluetoothUuid();
+
+ const quint128 original = serviceUuid.toUInt128();
+ quint128 reversed;
+ for (int i = 0; i < 16; i++)
+ reversed.data[15-i] = original.data[i];
+
+ return QBluetoothUuid(reversed);
+}
+
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
: socket(-1),
socketType(QBluetoothServiceInfo::UnknownProtocol),
@@ -206,7 +238,7 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channel)
{
- qCWarning(QT_BT_ANDROID) << "Falling back to workaround.";
+ qCWarning(QT_BT_ANDROID) << "Falling back to getServiceChannel() workaround.";
QAndroidJniEnvironment env;
@@ -320,6 +352,60 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
return true;
}
+/*
+ * Workaround for QTBUG-61392
+ */
+bool QBluetoothSocketPrivate::fallBackReversedConnect(const QBluetoothUuid &uuid)
+{
+ Q_Q(QBluetoothSocket);
+
+ qCWarning(QT_BT_ANDROID) << "Falling back to reverse uuid workaround.";
+ const QBluetoothUuid reverse = reverseUuid(uuid);
+ if (reverse.isNull())
+ return false;
+
+ //cut leading { and trailing } {xxx-xxx}
+ QString tempUuid = reverse.toString();
+ tempUuid.chop(1); //remove trailing '}'
+ tempUuid.remove(0, 1); //remove first '{'
+
+ QAndroidJniEnvironment env;
+ const QAndroidJniObject inputString = QAndroidJniObject::fromString(tempUuid);
+ const QAndroidJniObject uuidObject = QAndroidJniObject::callStaticObjectMethod("java/util/UUID", "fromString",
+ "(Ljava/lang/String;)Ljava/util/UUID;",
+ inputString.object<jstring>());
+
+ if (secFlags == QBluetooth::NoSecurity) {
+ qCDebug(QT_BT_ANDROID) << "Connnecting via insecure rfcomm";
+ socketObject = remoteDevice.callObjectMethod("createInsecureRfcommSocketToServiceRecord",
+ "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;",
+ uuidObject.object<jobject>());
+ } else {
+ qCDebug(QT_BT_ANDROID) << "Connnecting via secure rfcomm";
+ socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord",
+ "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;",
+ uuidObject.object<jobject>());
+ }
+
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ socketObject = remoteDevice = QAndroidJniObject();
+ errorString = QBluetoothSocket::tr("Cannot connect to %1",
+ "%1 = uuid").arg(reverse.toString());
+ q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
+ q->setSocketState(QBluetoothSocket::UnconnectedState);
+ return false;
+ }
+
+ WorkerThread *workerThread = new WorkerThread();
+ workerThread->setupWorker(this, socketObject, uuidObject, USE_FALLBACK);
+ workerThread->start();
+ emit connectJavaSocket();
+
+ return true;
+}
/*
* The call order during a connectToService() is as follows:
@@ -329,11 +415,14 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
* 3. if threaded connect succeeds call socketConnectSuccess() via signals
* -> done
* 4. if threaded connect fails call defaultSocketConnectFailed() via signals
- * 5. call fallBackConnect()
- * 6. if threaded connect on fallback channel succeeds call socketConnectSuccess()
+ * 5. call fallBackConnect() if Android version 22 or below
+ * -> Android 23+ complete failure of entire connectToService()
+ * 6. call fallBackReversedConnect() if Android version 23 or above
+ * -> if failure entire connectToService() fails
+ * 7. if threaded connect on one of above fallbacks succeeds call socketConnectSuccess()
* via signals
* -> done
- * 7. if threaded connect on fallback channel fails call fallbackSocketConnectFailed()
+ * 8. if threaded connect on fallback channel fails call fallbackSocketConnectFailed()
* -> complete failure of entire connectToService()
* */
void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
@@ -414,7 +503,7 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
}
WorkerThread *workerThread = new WorkerThread();
- workerThread->setupWorker(this, socketObject, uuidObject, !USE_FALLBACK);
+ workerThread->setupWorker(this, socketObject, uuidObject, !USE_FALLBACK, uuid);
workerThread->start();
emit connectJavaSocket();
}
@@ -480,7 +569,8 @@ void QBluetoothSocketPrivate::socketConnectSuccess(const QAndroidJniObject &sock
}
void QBluetoothSocketPrivate::defaultSocketConnectFailed(
- const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid)
+ const QAndroidJniObject &socket, const QAndroidJniObject &targetUuid,
+ const QBluetoothUuid &qtTargetUuid)
{
Q_Q(QBluetoothSocket);
@@ -489,7 +579,12 @@ void QBluetoothSocketPrivate::defaultSocketConnectFailed(
if (socket != socketObject)
return;
- bool success = fallBackConnect(targetUuid, FALLBACK_CHANNEL);
+ bool success = false;
+ if (QtAndroid::androidSdkVersion() <= 22)
+ success = fallBackConnect(targetUuid, FALLBACK_CHANNEL);
+ else if (useReverseUuidWorkAroundConnect) // version 23+ has Android bug (see QTBUG-61392)
+ success = fallBackReversedConnect(qtTargetUuid);
+
if (!success) {
errorString = QBluetoothSocket::tr("Connection to service failed");
socketObject = remoteDevice = QAndroidJniObject();
@@ -627,7 +722,6 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
env->SetByteArrayRegion(nativeData, 0, (qint32)maxSize, reinterpret_cast<const jbyte*>(data));
outputStream.callMethod<void>("write", "([BII)V", nativeData, 0, (qint32)maxSize);
env->DeleteLocalRef(nativeData);
- emit q->bytesWritten(maxSize);
if (env->ExceptionCheck()) {
qCWarning(QT_BT_ANDROID) << "Error while writing";
@@ -638,6 +732,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return -1;
}
+ emit q->bytesWritten(maxSize);
return maxSize;
}
@@ -784,6 +879,20 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
return 0;
}
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return 0; // nothing because always unbuffered
+}
+
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ // We cannot access buffer directly as it is part of different thread
+ if (inputThread)
+ return inputThread->canReadLine();
+
+ return false;
+}
+
QT_END_NAMESPACE
#include <qbluetoothsocket_android.moc>
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index 42c5503b..17b8e738 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -290,7 +290,9 @@ void QBluetoothSocketPrivate::_q_readNotify()
qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << socket << "error:" << readFromDevice << errorString;
if (errsv == EHOSTDOWN)
q->setSocketError(QBluetoothSocket::HostNotFoundError);
- else if (errsv != ECONNRESET) // The other side closing the connection is not an error.
+ else if (errsv == ECONNRESET)
+ q->setSocketError(QBluetoothSocket::RemoteHostClosedError);
+ else
q->setSocketError(QBluetoothSocket::UnknownSocketError);
q->disconnectFromService();
@@ -592,4 +594,14 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
return buffer.size();
}
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return txBuffer.size();
+}
+
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ return buffer.canReadLine();
+}
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm
index 75712868..de7e2120 100644
--- a/src/bluetooth/qbluetoothsocket_osx.mm
+++ b/src/bluetooth/qbluetoothsocket_osx.mm
@@ -60,7 +60,7 @@
QT_BEGIN_NAMESPACE
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : q_ptr(Q_NULLPTR),
+ : q_ptr(nullptr),
writeChunk(std::numeric_limits<UInt16>::max()),
openMode(QIODevice::NotOpen), // That's what is set in public class' ctors.
state(QBluetoothSocket::UnconnectedState),
@@ -443,6 +443,8 @@ qint64 QBluetoothSocket::bytesToWrite() const
void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
{
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
// Report this problem early, potentially avoid device discovery:
if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
@@ -480,6 +482,8 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
OpenMode openMode)
{
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
// Report this problem early, avoid device discovery:
if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
@@ -505,6 +509,8 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port,
OpenMode openMode)
{
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
@@ -571,6 +577,8 @@ void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError socketError)
void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
{
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
setSocketState(ServiceLookupState);
if (d_ptr->discoveryAgent)
@@ -761,12 +769,18 @@ QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error)
case QBluetoothSocket::HostNotFoundError:
debug << "QBluetoothSocket::HostNotFoundError";
break;
+ case QBluetoothSocket::RemoteHostClosedError:
+ debug << "QBluetoothSocket::RemoteHostClosedError";
+ break;
case QBluetoothSocket::ServiceNotFoundError:
debug << "QBluetoothSocket::ServiceNotFoundError";
break;
case QBluetoothSocket::NetworkError:
debug << "QBluetoothSocket::NetworkError";
break;
+ case QBluetoothSocket::UnsupportedProtocolError:
+ debug << "QBluetoothSocket::UnsupportedProtocolError";
+ break;
default:
debug << "QBluetoothSocket::SocketError(" << (int)error << ")";
}
diff --git a/src/bluetooth/qbluetoothsocket_osx_p.h b/src/bluetooth/qbluetoothsocket_osx_p.h
index 732d31aa..ce376702 100644
--- a/src/bluetooth/qbluetoothsocket_osx_p.h
+++ b/src/bluetooth/qbluetoothsocket_osx_p.h
@@ -104,7 +104,7 @@ public:
quint16 peerPort() const;
void _q_readNotify();
- void _q_writeNotify() Q_DECL_OVERRIDE;
+ void _q_writeNotify() override;
private:
// Create a socket from an external source (without connectToService).
@@ -112,11 +112,11 @@ private:
bool setChannel(IOBluetoothL2CAPChannel *channel);
// L2CAP and RFCOMM delegate
- void setChannelError(IOReturn errorCode) Q_DECL_OVERRIDE;
- void channelOpenComplete() Q_DECL_OVERRIDE;
- void channelClosed() Q_DECL_OVERRIDE;
- void readChannelData(void *data, std::size_t size) Q_DECL_OVERRIDE;
- void writeComplete() Q_DECL_OVERRIDE;
+ void setChannelError(IOReturn errorCode) override;
+ void channelOpenComplete() override;
+ void channelClosed() override;
+ void readChannelData(void *data, std::size_t size) override;
+ void writeComplete() override;
qint64 writeData(const char *data, qint64 maxSize);
qint64 readData(char *data, qint64 maxSize);
diff --git a/src/bluetooth/qbluetoothsocket_p.cpp b/src/bluetooth/qbluetoothsocket_p.cpp
index 6007b924..39d483d6 100644
--- a/src/bluetooth/qbluetoothsocket_p.cpp
+++ b/src/bluetooth/qbluetoothsocket_p.cpp
@@ -158,4 +158,14 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
return 0;
}
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ return false;
+}
+
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocket_p.h
index 956f8f02..907acbe2 100644
--- a/src/bluetooth/qbluetoothsocket_p.h
+++ b/src/bluetooth/qbluetoothsocket_p.h
@@ -77,8 +77,6 @@ namespace ABI {
}
}
}
-
-class SocketWorker;
#endif // QT_WINRT_BLUETOOTH
#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE
@@ -92,6 +90,10 @@ QT_FORWARD_DECLARE_CLASS(QSocketNotifier)
QT_BEGIN_NAMESPACE
+#ifdef QT_WINRT_BLUETOOTH
+class SocketWorker;
+#endif
+
class QBluetoothServiceDiscoveryAgent;
class QSocketServerPrivate
@@ -127,6 +129,7 @@ public:
#endif
#ifdef QT_ANDROID_BLUETOOTH
bool fallBackConnect(QAndroidJniObject uuid, int channel);
+ bool fallBackReversedConnect(const QBluetoothUuid &uuid);
#endif
@@ -165,6 +168,8 @@ public:
QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite);
qint64 bytesAvailable() const;
+ bool canReadLine() const;
+ qint64 bytesToWrite() const;
public:
QPrivateLinearBuffer buffer;
@@ -197,7 +202,8 @@ public:
public slots:
void socketConnectSuccess(const QAndroidJniObject &socket);
void defaultSocketConnectFailed(const QAndroidJniObject & socket,
- const QAndroidJniObject &targetUuid);
+ const QAndroidJniObject &targetUuid,
+ const QBluetoothUuid &qtTargetUuid);
void fallbackSocketConnectFailed(const QAndroidJniObject &socket,
const QAndroidJniObject &targetUuid);
void inputThreadError(int errorCode);
@@ -263,7 +269,7 @@ public slots:
#endif // QT_OSX_BLUETOOTH
-static inline void convertAddress(quint64 from, quint8 (&to)[6])
+static inline void convertAddress(const quint64 from, quint8 (&to)[6])
{
to[0] = (from >> 0) & 0xff;
to[1] = (from >> 8) & 0xff;
@@ -273,7 +279,7 @@ static inline void convertAddress(quint64 from, quint8 (&to)[6])
to[5] = (from >> 40) & 0xff;
}
-static inline quint64 convertAddress(quint8 (&from)[6], quint64 *to = 0)
+static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = 0)
{
const quint64 result = (quint64(from[0]) << 0) |
(quint64(from[1]) << 8) |
@@ -286,6 +292,15 @@ static inline quint64 convertAddress(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;
+
+#endif
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index 1f4e6233..ec511974 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -40,6 +40,9 @@
#include "qbluetoothsocket.h"
#include "qbluetoothsocket_p.h"
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include <qfunctions_winrt.h>
#include <private/qeventdispatcher_winrt_p.h>
@@ -223,7 +226,7 @@ public:
// the closing of the socket won't be communicated to the caller. So only the error is set. The
// actual socket close happens inside of read.
if (!bufferLength) {
- emit socketErrorOccured(QBluetoothSocket::NetworkError);
+ emit socketErrorOccured(QBluetoothSocket::RemoteHostClosedError);
return S_OK;
}
@@ -422,6 +425,9 @@ QString QBluetoothSocketPrivate::localName() const
QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
{
+ if (!m_socketObject)
+ return QBluetoothAddress();
+
HRESULT hr;
ComPtr<IStreamSocketInformation> info;
hr = m_socketObject->get_Information(&info);
@@ -437,6 +443,9 @@ QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
quint16 QBluetoothSocketPrivate::localPort() const
{
+ if (!m_socketObject)
+ return 0;
+
HRESULT hr;
ComPtr<IStreamSocketInformation> info;
hr = m_socketObject->get_Information(&info);
@@ -449,6 +458,9 @@ quint16 QBluetoothSocketPrivate::localPort() const
QString QBluetoothSocketPrivate::peerName() const
{
+ if (!m_socketObject)
+ return QString();
+
HRESULT hr;
ComPtr<IStreamSocketInformation> info;
hr = m_socketObject->get_Information(&info);
@@ -464,6 +476,9 @@ QString QBluetoothSocketPrivate::peerName() const
QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
{
+ if (!m_socketObject)
+ return QBluetoothAddress();
+
HRESULT hr;
ComPtr<IStreamSocketInformation> info;
hr = m_socketObject->get_Information(&info);
@@ -479,6 +494,9 @@ QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
quint16 QBluetoothSocketPrivate::peerPort() const
{
+ if (!m_socketObject)
+ return 0;
+
HRESULT hr;
ComPtr<IStreamSocketInformation> info;
hr = m_socketObject->get_Information(&info);
@@ -569,6 +587,16 @@ qint64 QBluetoothSocketPrivate::bytesAvailable() const
return buffer.size();
}
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return 0; // nothing because always unbuffered
+}
+
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ return buffer.canReadLine();
+}
+
void QBluetoothSocketPrivate::handleNewData(const QVector<QByteArray> &data)
{
// Defer putting the data into the list until the next event loop iteration
@@ -584,6 +612,9 @@ void QBluetoothSocketPrivate::handleError(QBluetoothSocket::SocketError error)
case QBluetoothSocket::NetworkError:
errorString = QBluetoothSocket::tr("Network error");
break;
+ case QBluetoothSocket::RemoteHostClosedError:
+ errorString = QBluetoothSocket::tr("Remote host closed connection");
+ break;
default:
errorString = QBluetoothSocket::tr("Unknown socket error");
}
diff --git a/src/bluetooth/qbluetoothtransfermanager.h b/src/bluetooth/qbluetoothtransfermanager.h
index d1171588..98850392 100644
--- a/src/bluetooth/qbluetoothtransfermanager.h
+++ b/src/bluetooth/qbluetoothtransfermanager.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHTRANSFERMANAGER_H
#define QBLUETOOTHTRANSFERMANAGER_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/QBluetoothAddress>
#include <QtCore/QObject>
@@ -58,7 +58,7 @@ class Q_BLUETOOTH_EXPORT QBluetoothTransferManager : public QObject
Q_OBJECT
public:
- explicit QBluetoothTransferManager(QObject *parent = Q_NULLPTR);
+ explicit QBluetoothTransferManager(QObject *parent = nullptr);
~QBluetoothTransferManager();
QBluetoothTransferReply *put(const QBluetoothTransferRequest &request, QIODevice *data);
diff --git a/src/bluetooth/qbluetoothtransferreply.h b/src/bluetooth/qbluetoothtransferreply.h
index c2b0b622..8f0679f5 100644
--- a/src/bluetooth/qbluetoothtransferreply.h
+++ b/src/bluetooth/qbluetoothtransferreply.h
@@ -88,7 +88,7 @@ Q_SIGNALS:
void error(QBluetoothTransferReply::TransferError lastError);
protected:
- explicit QBluetoothTransferReply(QObject *parent = Q_NULLPTR);
+ explicit QBluetoothTransferReply(QObject *parent = nullptr);
void setManager(QBluetoothTransferManager *manager);
void setRequest(const QBluetoothTransferRequest &request);
diff --git a/src/bluetooth/qbluetoothtransferreply_osx.mm b/src/bluetooth/qbluetoothtransferreply_osx.mm
index 02133860..65c8f82d 100644
--- a/src/bluetooth/qbluetoothtransferreply_osx.mm
+++ b/src/bluetooth/qbluetoothtransferreply_osx.mm
@@ -75,14 +75,14 @@ public:
private:
// OBEX session delegate:
- void OBEXConnectError(OBEXError errorCode, OBEXOpCode response) Q_DECL_OVERRIDE;
- void OBEXConnectSuccess() Q_DECL_OVERRIDE;
+ void OBEXConnectError(OBEXError errorCode, OBEXOpCode response) override;
+ void OBEXConnectSuccess() override;
- void OBEXAbortSuccess() Q_DECL_OVERRIDE;
+ void OBEXAbortSuccess() override;
- void OBEXPutDataSent(quint32 current, quint32 total) Q_DECL_OVERRIDE;
- void OBEXPutSuccess() Q_DECL_OVERRIDE;
- void OBEXPutError(OBEXError error, OBEXOpCode response) Q_DECL_OVERRIDE;
+ void OBEXPutDataSent(quint32 current, quint32 total) override;
+ void OBEXPutSuccess() override;
+ void OBEXPutError(OBEXError error, OBEXOpCode response) override;
QBluetoothTransferReplyOSX *q_ptr;
@@ -394,7 +394,7 @@ bool QBluetoothTransferReplyOSX::abort()
// Reset a delegate.
[osx_d_ptr->session closeSession];
// Should never be called from an OBEX callback!
- osx_d_ptr->session.reset(Q_NULLPTR);
+ osx_d_ptr->session.reset(nullptr);
// Not setReplyError, we emit finished only!
osx_d_ptr->requestComplete = true;
diff --git a/src/bluetooth/qbluetoothtransferreply_osx_p.h b/src/bluetooth/qbluetoothtransferreply_osx_p.h
index d77d4913..e7b6f683 100644
--- a/src/bluetooth/qbluetoothtransferreply_osx_p.h
+++ b/src/bluetooth/qbluetoothtransferreply_osx_p.h
@@ -73,11 +73,11 @@ public:
QBluetoothTransferManager *parent);
~QBluetoothTransferReplyOSX();
- TransferError error() const Q_DECL_OVERRIDE;
- QString errorString() const Q_DECL_OVERRIDE;
+ TransferError error() const override;
+ QString errorString() const override;
- bool isFinished() const Q_DECL_OVERRIDE;
- bool isRunning() const Q_DECL_OVERRIDE;
+ bool isFinished() const override;
+ bool isRunning() const override;
Q_SIGNALS:
void error(QBluetoothTransferReply::TransferError lastError);
diff --git a/src/bluetooth/qbluetoothtransferrequest.h b/src/bluetooth/qbluetoothtransferrequest.h
index 006f1ced..5485a0d9 100644
--- a/src/bluetooth/qbluetoothtransferrequest.h
+++ b/src/bluetooth/qbluetoothtransferrequest.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHTRANSFERREQUEST_H
#define QBLUETOOTHTRANSFERREQUEST_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/QBluetoothAddress>
#include <QtCore/QtGlobal>
diff --git a/src/bluetooth/qbluetoothtransferrequest_p.h b/src/bluetooth/qbluetoothtransferrequest_p.h
index d8b2e55d..410a9709 100644
--- a/src/bluetooth/qbluetoothtransferrequest_p.h
+++ b/src/bluetooth/qbluetoothtransferrequest_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include "qbluetoothtransferrequest.h"
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qbluetoothutils_win.cpp b/src/bluetooth/qbluetoothutils_win.cpp
new file mode 100644
index 00000000..fa3127cb
--- /dev/null
+++ b/src/bluetooth/qbluetoothutils_win.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#define Q_OS_WINRT
+#include <QtCore/qfunctions_winrt.h>
+
+#include <wrl.h>
+#include <windows.devices.bluetooth.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Devices::Bluetooth;
+using namespace ABI::Windows::Foundation;
+
+QT_BEGIN_NAMESPACE
+
+#pragma warning (push)
+#pragma warning (disable: 4273)
+HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT()> &delegate, bool waitForRun)
+{
+ Q_UNUSED(waitForRun)
+ return delegate();
+}
+#pragma warning (pop)
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH: {
+ // Check if we are running on a recent enough Windows
+ HRESULT hr = OleInitialize(NULL);
+ if (FAILED(hr)) {
+ MessageBox(NULL, (LPCWSTR)L"OleInitialize failed.", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
+ exit(-1);
+ }
+ ComPtr<IBluetoothDeviceStatics> deviceStatics;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothDevice).Get(), &deviceStatics);
+ if (hr == REGDB_E_CLASSNOTREG) {
+ QString error ("This Windows version (" + QSysInfo::kernelVersion() + ") does not "
+ "support the required Bluetooth API. Consider updating to a more recent Windows "
+ "(10.0.10586 or above).");
+ MessageBox(NULL, (LPCWSTR)error.constData(), (LPCWSTR)L"Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
+ CoUninitialize();
+ exit(-1);
+ }
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ CoUninitialize();
+ }
+
+ return TRUE;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h
index fb301c37..28b08583 100644
--- a/src/bluetooth/qbluetoothuuid.h
+++ b/src/bluetooth/qbluetoothuuid.h
@@ -40,7 +40,7 @@
#ifndef QBLUETOOTHUUID_H
#define QBLUETOOTHUUID_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/QtGlobal>
#include <QtCore/QMetaType>
@@ -383,8 +383,8 @@ public:
int minimumSize() const;
- quint16 toUInt16(bool *ok = Q_NULLPTR) const;
- quint32 toUInt32(bool *ok = Q_NULLPTR) const;
+ quint16 toUInt16(bool *ok = nullptr) const;
+ quint32 toUInt32(bool *ok = nullptr) const;
quint128 toUInt128() const;
static QString serviceClassToString(ServiceClassUuid uuid);
diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp
index ff00b2b1..b964f620 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -102,7 +102,6 @@ void QLeAdvertiserBluez::doStartAdvertising()
return;
}
- m_disableCommandFinished = false;
m_sendPowerLevel = advertisingData().includePowerLevel()
|| scanResponseData().includePowerLevel();
if (m_sendPowerLevel)
@@ -115,6 +114,7 @@ void QLeAdvertiserBluez::doStartAdvertising()
void QLeAdvertiserBluez::doStopAdvertising()
{
toggleAdvertising(false);
+ sendNextCommand();
}
void QLeAdvertiserBluez::queueCommand(OpCodeCommandField ocf, const QByteArray &data)
@@ -408,14 +408,17 @@ void QLeAdvertiserBluez::handleCommandCompleted(quint16 opCode, quint8 status,
if (m_pendingCommands.isEmpty())
return;
const quint16 ocf = ocfFromOpCode(opCode);
- if (m_pendingCommands.first().ocf != ocf)
+ const Command currentCmd = m_pendingCommands.first();
+ if (currentCmd.ocf != ocf)
return; // Not one of our commands.
m_pendingCommands.takeFirst();
if (status != 0) {
qCDebug(QT_BT_BLUEZ) << "command" << ocf << "failed with status" << status;
- if (ocf == OcfLeSetAdvEnable && !m_disableCommandFinished && status == 0xc) {
- qCDebug(QT_BT_BLUEZ) << "initial advertising disable failed, ignoring";
- m_disableCommandFinished = true;
+ if (ocf == OcfLeSetAdvEnable && status == 0xc && currentCmd.data == QByteArray(1, '\0')) {
+ // we ignore OcfLeSetAdvEnable if it tries to disable an active advertisement
+ // it seems the platform often automatically turns off advertisements
+ // subsequently the explicit stopAdvertisement call fails when re-issued
+ qCDebug(QT_BT_BLUEZ) << "Advertising disable failed, ignoring";
sendNextCommand();
return;
}
@@ -439,10 +442,6 @@ void QLeAdvertiserBluez::handleCommandCompleted(quint16 opCode, quint8 status,
}
queueAdvertisingCommands();
break;
- case OcfLeSetAdvEnable:
- if (!m_disableCommandFinished)
- m_disableCommandFinished = true;
- break;
default:
break;
}
diff --git a/src/bluetooth/qleadvertiser_p.h b/src/bluetooth/qleadvertiser_p.h
index 922fdf64..e8f55bda 100644
--- a/src/bluetooth/qleadvertiser_p.h
+++ b/src/bluetooth/qleadvertiser_p.h
@@ -145,7 +145,6 @@ private:
quint8 m_powerLevel;
bool m_sendPowerLevel;
- bool m_disableCommandFinished;
};
#endif // QT_CONFIG(bluez)
diff --git a/src/bluetooth/qlowenergyadvertisingdata.h b/src/bluetooth/qlowenergyadvertisingdata.h
index 904c5c2b..0fc55adb 100644
--- a/src/bluetooth/qlowenergyadvertisingdata.h
+++ b/src/bluetooth/qlowenergyadvertisingdata.h
@@ -40,7 +40,7 @@
#ifndef QLOWENERGYADVERTISINGDATA_H
#define QLOWENERGYADVERTISINGDATA_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/qbluetoothuuid.h>
#include <QtCore/qshareddata.h>
diff --git a/src/bluetooth/qlowenergyadvertisingparameters.h b/src/bluetooth/qlowenergyadvertisingparameters.h
index 547e5798..055026e6 100644
--- a/src/bluetooth/qlowenergyadvertisingparameters.h
+++ b/src/bluetooth/qlowenergyadvertisingparameters.h
@@ -40,7 +40,7 @@
#ifndef QLOWENERGYADVERTISINGPARAMETERS_H
#define QLOWENERGYADVERTISINGPARAMETERS_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtBluetooth/qbluetoothaddress.h>
#include <QtBluetooth/qlowenergycontroller.h>
#include <QtCore/qlist.h>
diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h
index b991e9a2..154c9936 100644
--- a/src/bluetooth/qlowenergycharacteristic.h
+++ b/src/bluetooth/qlowenergycharacteristic.h
@@ -107,4 +107,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyCharacteristic::PropertyTypes)
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QLowEnergyCharacteristic)
+
#endif // QLOWENERGYCHARACTERISTIC_H
diff --git a/src/bluetooth/qlowenergyconnectionparameters.h b/src/bluetooth/qlowenergyconnectionparameters.h
index 9a3896c3..c765763f 100644
--- a/src/bluetooth/qlowenergyconnectionparameters.h
+++ b/src/bluetooth/qlowenergyconnectionparameters.h
@@ -40,7 +40,7 @@
#ifndef QLOWENERGYCONNECTIONPARAMETERS_H
#define QLOWENERGYCONNECTIONPARAMETERS_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qshareddata.h>
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index a3aad282..7cd80072 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** 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.
@@ -138,6 +138,8 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
This value was introduced by Qt 5.5.
\value AdvertisingError The attempt to start advertising failed.
This value was introduced by Qt 5.7.
+ \value RemoteHostClosedError The remote device closed the connection.
+ This value was introduced by Qt 5.10.
*/
/*!
@@ -299,6 +301,9 @@ void QLowEnergyControllerPrivate::setError(
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:
@@ -691,6 +696,19 @@ QLowEnergyController::RemoteAddressType QLowEnergyController::remoteAddressType(
/*!
Sets the remote address \a type. The type is required to connect
to the remote Bluetooth Low Energy device.
+
+ This attribute is only required to be set on Linux/BlueZ systems with older
+ Linux kernels (v3.3 or lower), or if CAP_NET_ADMIN is not set for the executable.
+ The default value of the attribute is \l RandomAddress.
+
+ \note All other platforms handle this flag transparently and therefore applications
+ can ignore it entirely. On Linux, the address type flag is not directly exposed
+ by BlueZ although some use cases do require this information. The only way to detect
+ the flag is via the Linux kernel's Bluetooth Management API (kernel
+ version 3.4+ required). This API requires CAP_NET_ADMIN capabilities though. If the
+ local QtBluetooth process has this capability set QtBluetooth will use the API. This
+ assumes that \l QBluetoothDeviceDiscoveryAgent was used prior to calling
+ \l QLowEnergyController::connectToDevice().
*/
void QLowEnergyController::setRemoteAddressType(
QLowEnergyController::RemoteAddressType type)
@@ -832,7 +850,7 @@ QLowEnergyService *QLowEnergyController::createServiceObject(
{
Q_D(QLowEnergyController);
- QLowEnergyService *service = Q_NULLPTR;
+ QLowEnergyService *service = nullptr;
ServiceDataMap::const_iterator it = d->serviceList.constFind(serviceUuid);
if (it != d->serviceList.constEnd()) {
@@ -918,13 +936,24 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
return nullptr;
}
+ Q_D(QLowEnergyController);
+ QLowEnergyService *newService = d->addServiceHelper(service);
+ if (newService)
+ newService->setParent(parent);
+
+ 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(d_ptr);
+ servicePrivate->setController(this);
servicePrivate->uuid = service.uuid();
servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary
? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService;
@@ -934,13 +963,13 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
}
// Spec v4.2, Vol 3, Part G, Section 3.
- const QLowEnergyHandle oldLastHandle = d_ptr->lastLocalHandle;
- servicePrivate->startHandle = ++d_ptr->lastLocalHandle; // Service declaration.
- d_ptr->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations.
+ 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 = ++d_ptr->lastLocalHandle;
+ const QLowEnergyHandle declHandle = ++this->lastLocalHandle;
QLowEnergyServicePrivate::CharData charData;
- charData.valueHandle = ++d_ptr->lastLocalHandle;
+ charData.valueHandle = ++this->lastLocalHandle;
charData.uuid = cd.uuid();
charData.properties = cd.properties();
charData.value = cd.value();
@@ -948,21 +977,21 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
QLowEnergyServicePrivate::DescData descData;
descData.uuid = dd.uuid();
descData.value = dd.value();
- charData.descriptorList.insert(++d_ptr->lastLocalHandle, descData);
+ charData.descriptorList.insert(++this->lastLocalHandle, descData);
}
servicePrivate->characteristicList.insert(declHandle, charData);
}
- servicePrivate->endHandle = d_ptr->lastLocalHandle;
- const bool handleOverflow = d_ptr->lastLocalHandle <= oldLastHandle;
+ servicePrivate->endHandle = this->lastLocalHandle;
+ const bool handleOverflow = this->lastLocalHandle <= oldLastHandle;
if (handleOverflow) {
qCWarning(QT_BT) << "Not enough attribute handles left to create this service";
- d_ptr->lastLocalHandle = oldLastHandle;
+ this->lastLocalHandle = oldLastHandle;
return nullptr;
}
- d_ptr->localServices.insert(servicePrivate->uuid, servicePrivate);
- d_ptr->addToGenericAttributeList(service, servicePrivate->startHandle);
- return new QLowEnergyService(servicePrivate, parent);
+ this->localServices.insert(servicePrivate->uuid, servicePrivate);
+ this->addToGenericAttributeList(service, servicePrivate->startHandle);
+ return new QLowEnergyService(servicePrivate);
}
/*!
diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h
index 1c4fa83f..f9e6ef5d 100644
--- a/src/bluetooth/qlowenergycontroller.h
+++ b/src/bluetooth/qlowenergycontroller.h
@@ -66,6 +66,7 @@ public:
InvalidBluetoothAdapterError,
ConnectionError,
AdvertisingError,
+ RemoteHostClosedError
};
Q_ENUM(Error)
@@ -90,12 +91,12 @@ public:
Q_ENUM(Role)
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
- QObject *parent = Q_NULLPTR); // TODO Qt 6 remove ctor
+ QObject *parent = nullptr); // TODO Qt 6 remove ctor
explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent = Q_NULLPTR);
+ QObject *parent = nullptr);
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
const QBluetoothAddress &localDevice,
- QObject *parent = Q_NULLPTR); // TODO Qt 6 remove ctor
+ QObject *parent = nullptr); // TODO Qt 6 remove ctor
static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice,
QObject *parent = nullptr);
@@ -121,7 +122,7 @@ public:
void discoverServices();
QList<QBluetoothUuid> services() const;
- QLowEnergyService *createServiceObject(const QBluetoothUuid &service, QObject *parent = Q_NULLPTR);
+ QLowEnergyService *createServiceObject(const QBluetoothUuid &service, QObject *parent = nullptr);
void startAdvertising(const QLowEnergyAdvertisingParameters &parameters,
const QLowEnergyAdvertisingData &advertisingData,
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index e5a3d8de..ca3f7760 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2016 Javier S. Pedro <maemo@javispedro.com>
** Contact: https://www.qt.io/licensing/
**
@@ -44,6 +44,9 @@
#include "qleadvertiser_p.h"
#include "bluez/bluez_data_p.h"
#include "bluez/hcimanager_p.h"
+#include "bluez/remotedevicemanager_p.h"
+#include "bluez/bluez5_helper_p.h"
+#include "bluez/bluetoothmanagement_p.h"
#include <QtCore/QFileInfo>
#include <QtCore/QLoggingCategory>
@@ -527,6 +530,70 @@ void QLowEnergyControllerPrivate::connectToDevice()
if (l2cpSocket)
delete l2cpSocket;
+ createServicesForCentralIfRequired();
+
+ // check for active running connections
+ // BlueZ 5.37+ (maybe even earlier versions) can have pending BTLE connections
+ // Only one active L2CP socket to CID 0x4 possible at a time
+ // this check is not performed for BlueZ 4 based platforms as bluetoothd
+ // does not support BTLE management
+
+ if (!isBluez5()) {
+ establishL2cpClientSocket();
+ return;
+ }
+
+ QVector<quint16> activeHandles = hciManager->activeLowEnergyConnections();
+ if (!activeHandles.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot connect due to pending active LE connections";
+
+ if (!device1Manager) {
+ device1Manager = new RemoteDeviceManager(localAdapter, this);
+ connect(device1Manager, &RemoteDeviceManager::finished,
+ this, &QLowEnergyControllerPrivate::activeConnectionTerminationDone);
+ }
+
+ QVector<QBluetoothAddress> connectedAddresses;
+ for (const auto handle: activeHandles) {
+ const QBluetoothAddress addr = hciManager->addressForConnectionHandle(handle);
+ if (!addr.isNull())
+ connectedAddresses.push_back(addr);
+ }
+ device1Manager->scheduleJob(RemoteDeviceManager::JobType::JobDisconnectDevice, connectedAddresses);
+ } else {
+ establishL2cpClientSocket();
+ }
+}
+
+/*!
+ * Handles outcome of attempts to close external connections.
+ */
+void QLowEnergyControllerPrivate::activeConnectionTerminationDone()
+{
+ if (!device1Manager)
+ return;
+
+ qCDebug(QT_BT_BLUEZ) << "RemoteDeviceManager finished attempting"
+ << "to close external connections";
+
+ QVector<quint16> activeHandles = hciManager->activeLowEnergyConnections();
+ if (!activeHandles.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ } else {
+ establishL2cpClientSocket();
+ }
+}
+
+/*!
+ * Establishes the L2CP client socket.
+ */
+void QLowEnergyControllerPrivate::establishL2cpClientSocket()
+{
+ //we are already in Connecting state
+
l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this);
connect(l2cpSocket, SIGNAL(connected()), this, SLOT(l2cpConnected()));
connect(l2cpSocket, SIGNAL(disconnected()), this, SLOT(l2cpDisconnected()));
@@ -534,10 +601,20 @@ void QLowEnergyControllerPrivate::connectToDevice()
this, SLOT(l2cpErrorChanged(QBluetoothSocket::SocketError)));
connect(l2cpSocket, SIGNAL(readyRead()), this, SLOT(l2cpReadyRead()));
- if (addressType == QLowEnergyController::PublicAddress)
- l2cpSocket->d_ptr->lowEnergySocketType = BDADDR_LE_PUBLIC;
- else if (addressType == QLowEnergyController::RandomAddress)
- l2cpSocket->d_ptr->lowEnergySocketType = BDADDR_LE_RANDOM;
+ quint32 addressTypeToUse = (addressType == QLowEnergyController::PublicAddress)
+ ? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM;
+ if (BluetoothManagement::instance()->isMonitoringEnabled()) {
+ // if monitoring is possible and it's private then we force it to the relevant option
+ if (BluetoothManagement::instance()->isAddressRandom(remoteDevice)) {
+ addressTypeToUse = BDADDR_LE_RANDOM;
+ }
+ }
+
+ qCDebug(QT_BT_BLUEZ) << "addresstypeToUse:"
+ << (addressTypeToUse == BDADDR_LE_RANDOM
+ ? QStringLiteral("Random") : QStringLiteral("Public"));
+
+ l2cpSocket->d_ptr->lowEnergySocketType = addressTypeToUse;
int sockfd = l2cpSocket->socketDescriptor();
if (sockfd < 0) {
@@ -569,6 +646,72 @@ void QLowEnergyControllerPrivate::connectToDevice()
loadSigningDataIfNecessary(LocalSigningKey);
}
+void QLowEnergyControllerPrivate::createServicesForCentralIfRequired()
+{
+ bool ok = false;
+ int value = qEnvironmentVariableIntValue("QT_DEFAULT_CENTRAL_SERVICES", &ok);
+ if (Q_UNLIKELY(ok && value == 0))
+ return; //nothing to do
+
+ //do not add the services each time we start a connection
+ if (localServices.contains(QBluetoothUuid(QBluetoothUuid::GenericAccess)))
+ return;
+
+ qCDebug(QT_BT_BLUEZ) << "Creating default GAP/GATT services";
+
+ //populate Generic Access service
+ //for now the values are static
+ QLowEnergyServiceData gapServiceData;
+ gapServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+ gapServiceData.setUuid(QBluetoothUuid::GenericAccess);
+
+ QLowEnergyCharacteristicData gapDeviceName;
+ gapDeviceName.setUuid(QBluetoothUuid::DeviceName);
+ gapDeviceName.setProperties(QLowEnergyCharacteristic::Read);
+
+ QBluetoothLocalDevice mainAdapter;
+ gapDeviceName.setValue(mainAdapter.name().toLatin1()); //static name
+
+ QLowEnergyCharacteristicData gapAppearance;
+ gapAppearance.setUuid(QBluetoothUuid::Appearance);
+ gapAppearance.setProperties(QLowEnergyCharacteristic::Read);
+ gapAppearance.setValue(QByteArray::fromHex("80")); // Generic Computer (0x80)
+
+ QLowEnergyCharacteristicData gapPrivacyFlag;
+ gapPrivacyFlag.setUuid(QBluetoothUuid::PeripheralPrivacyFlag);
+ gapPrivacyFlag.setProperties(QLowEnergyCharacteristic::Read);
+ gapPrivacyFlag.setValue(QByteArray::fromHex("00")); // disable privacy
+
+ gapServiceData.addCharacteristic(gapDeviceName);
+ gapServiceData.addCharacteristic(gapAppearance);
+ gapServiceData.addCharacteristic(gapPrivacyFlag);
+
+ Q_Q(QLowEnergyController);
+ QLowEnergyService *service = addServiceHelper(gapServiceData);
+ if (service)
+ service->setParent(q);
+
+ QLowEnergyServiceData gattServiceData;
+ gattServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+ gattServiceData.setUuid(QBluetoothUuid::GenericAttribute);
+
+ QLowEnergyCharacteristicData serviceChangedChar;
+ serviceChangedChar.setUuid(QBluetoothUuid::ServiceChanged);
+ serviceChangedChar.setProperties(QLowEnergyCharacteristic::Indicate);
+ //arbitrary range of 2 bit handle range (1-4
+ serviceChangedChar.setValue(QByteArray::fromHex("0104"));
+
+ const QLowEnergyDescriptorData clientConfig(
+ QBluetoothUuid::ClientCharacteristicConfiguration,
+ QByteArray(2, 0));
+ serviceChangedChar.addDescriptor(clientConfig);
+ gattServiceData.addCharacteristic(serviceChangedChar);
+
+ service = addServiceHelper(gattServiceData);
+ if (service)
+ service->setParent(q);
+}
+
void QLowEnergyControllerPrivate::l2cpConnected()
{
Q_Q(QLowEnergyController);
@@ -610,6 +753,10 @@ void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError
setError(QLowEnergyController::NetworkError);
qCDebug(QT_BT_BLUEZ) << "Network IO error while talking to LE device";
break;
+ case QBluetoothSocket::RemoteHostClosedError:
+ setError(QLowEnergyController::RemoteHostClosedError);
+ qCDebug(QT_BT_BLUEZ) << "Remote host closed the connection";
+ break;
case QBluetoothSocket::UnknownSocketError:
case QBluetoothSocket::UnsupportedProtocolError:
case QBluetoothSocket::OperationError:
@@ -1601,9 +1748,9 @@ void QLowEnergyControllerPrivate::readServiceValuesByOffset(
{
const QLowEnergyHandle charHandle = (handleData & 0xffff);
const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff);
- quint8 packet[READ_REQUEST_HEADER_SIZE];
- packet[0] = ATT_OP_READ_BLOB_REQUEST;
+ QByteArray data(READ_BLOB_REQUEST_HEADER_SIZE, Qt::Uninitialized);
+ data[0] = ATT_OP_READ_BLOB_REQUEST;
QLowEnergyHandle handleToRead = charHandle;
if (descriptorHandle) {
@@ -1624,11 +1771,8 @@ void QLowEnergyControllerPrivate::readServiceValuesByOffset(
}
}
- putBtData(handleToRead, &packet[1]);
- putBtData(offset, &packet[3]);
-
- QByteArray data(READ_BLOB_REQUEST_HEADER_SIZE, Qt::Uninitialized);
- memcpy(data.data(), packet, READ_BLOB_REQUEST_HEADER_SIZE);
+ putBtData(handleToRead, data.data() + 1);
+ putBtData(offset, data.data() + 3);
Request request;
request.payload = data;
@@ -1768,8 +1912,10 @@ bool QLowEnergyControllerPrivate::setSecurityLevel(int level)
switch (level) { // fall through intendeds
case BT_SECURITY_HIGH:
optval |= L2CAP_LM_SECURE;
+ Q_FALLTHROUGH();
case BT_SECURITY_MEDIUM:
optval |= L2CAP_LM_ENCRYPT;
+ Q_FALLTHROUGH();
case BT_SECURITY_LOW:
optval |= L2CAP_LM_AUTH;
break;
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm
index a2923d81..1206ef42 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_osx.mm
@@ -962,7 +962,7 @@ void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::E
void QLowEnergyControllerPrivateOSX::invalidateServices()
{
foreach (const QSharedPointer<QLowEnergyServicePrivate> service, discoveredServices.values()) {
- service->setController(Q_NULLPTR);
+ service->setController(nullptr);
service->setState(QLowEnergyService::InvalidService);
}
@@ -1228,7 +1228,7 @@ QLowEnergyService *QLowEnergyController::createServiceObject(const QBluetoothUui
{
OSX_D_PTR;
- QLowEnergyService *service = Q_NULLPTR;
+ QLowEnergyService *service = nullptr;
QLowEnergyControllerPrivateOSX::ServiceMap::const_iterator it = osx_d_ptr->discoveredServices.constFind(serviceUuid);
if (it != osx_d_ptr->discoveredServices.constEnd()) {
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index 1d7c02a2..84d307c1 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -85,8 +85,6 @@ QT_END_NAMESPACE
#elif defined(QT_WINRT_BLUETOOTH)
#include <wrl.h>
#include <windows.devices.bluetooth.h>
-
-class QWinRTLowEnergyServiceHandler;
#endif
#include <functional>
@@ -100,8 +98,11 @@ class QTimer;
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();
@@ -146,6 +147,8 @@ public:
QLowEnergyHandle handle);
QLowEnergyDescriptor descriptorForHandle(
QLowEnergyHandle handle);
+ QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service);
+
quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
const QByteArray &value,
@@ -279,6 +282,7 @@ private:
QLeAdvertiser *advertiser;
QSocketNotifier *serverSocketNotifier;
QTimer *requestTimer = nullptr;
+ RemoteDeviceManager* device1Manager = nullptr;
/*
Defines the maximum number of milliseconds the implementation will
@@ -413,6 +417,8 @@ private:
const QByteArray &newValue);
void restartRequestTimer();
+ void establishL2cpClientSocket();
+ void createServicesForCentralIfRequired();
private slots:
void l2cpConnected();
@@ -421,6 +427,7 @@ private slots:
void l2cpReadyRead();
void encryptionChangedEvent(const QBluetoothAddress&, bool);
void handleGattRequestTimeout();
+ void activeConnectionTerminationDone();
#elif defined(QT_ANDROID_BLUETOOTH)
LowEnergyNotificationHub *hub;
@@ -496,11 +503,6 @@ Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivate::Attribute, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-#ifdef QT_WINRT_BLUETOOTH
-Q_DECLARE_METATYPE(QLowEnergyCharacteristic)
-Q_DECLARE_METATYPE(QLowEnergyDescriptor)
-#endif // QT_WINRT_BLUETOOTH
-
#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 d6fc4952..62b8a9d3 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -39,6 +39,9 @@
#include "qlowenergycontroller_p.h"
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QLoggingCategory>
#include <private/qeventdispatcher_winrt_p.h>
@@ -338,6 +341,7 @@ void QLowEnergyControllerPrivate::connectToDevice()
emit q->connected();
} else if (state == QLowEnergyController::ConnectedState
&& status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
+ setError(QLowEnergyController::RemoteHostClosedError);
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
}
@@ -419,6 +423,10 @@ void QLowEnergyControllerPrivate::disconnectFromDevice()
Q_Q(QLowEnergyController);
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
+ if (mDevice && mStatusChangedToken.value) {
+ mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
+ mStatusChangedToken.value = 0;
+ }
}
ComPtr<IGattDeviceService> QLowEnergyControllerPrivate::getNativeService(const QBluetoothUuid &serviceUuid)
diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h
index 1dfe1c35..9e71fc56 100644
--- a/src/bluetooth/qlowenergydescriptor.h
+++ b/src/bluetooth/qlowenergydescriptor.h
@@ -89,4 +89,6 @@ protected:
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QLowEnergyDescriptor)
+
#endif // QLOWENERGYDESCRIPTOR_H
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 6e33c565..35a3a7d0 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -380,6 +380,8 @@ 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)));
@@ -630,7 +632,7 @@ void QLowEnergyService::readCharacteristic(
{
Q_D(QLowEnergyService);
- if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) {
+ if (d->controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) {
d->setError(QLowEnergyService::OperationError);
return;
}
@@ -701,7 +703,7 @@ void QLowEnergyService::writeCharacteristic(
//TODO check behavior when writing to WriteSigned characteristic
Q_D(QLowEnergyService);
- if (d->controller == Q_NULLPTR
+ if (d->controller == nullptr
|| (d->controller->role == QLowEnergyController::CentralRole
&& state() != ServiceDiscovered)
|| !contains(characteristic)) {
@@ -760,7 +762,7 @@ void QLowEnergyService::readDescriptor(
{
Q_D(QLowEnergyService);
- if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) {
+ if (d->controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
d->setError(QLowEnergyService::OperationError);
return;
}
@@ -802,7 +804,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
{
Q_D(QLowEnergyService);
- if (d->controller == Q_NULLPTR
+ if (d->controller == nullptr
|| (d->controller->role == QLowEnergyController::CentralRole
&& state() != ServiceDiscovered)
|| !contains(descriptor)) {
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index f138459f..3f6cfd88 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -136,7 +136,7 @@ private:
friend class QLowEnergyController;
friend class QLowEnergyControllerPrivate;
QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
- QObject *parent = Q_NULLPTR);
+ QObject *parent = nullptr);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyService::ServiceTypes)
diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm
index 52c2ac87..4423887a 100644
--- a/src/bluetooth/qlowenergyservice_osx.mm
+++ b/src/bluetooth/qlowenergyservice_osx.mm
@@ -58,7 +58,7 @@ namespace {
QLowEnergyControllerPrivateOSX *qt_mac_le_controller(QSharedPointer<QLowEnergyServicePrivate> d_ptr)
{
if (d_ptr.isNull())
- return Q_NULLPTR;
+ return nullptr;
return static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr->controller.data());
}
@@ -195,7 +195,7 @@ bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic)
void QLowEnergyService::readCharacteristic(const QLowEnergyCharacteristic &characteristic)
{
QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) {
+ if (controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) {
d_ptr->setError(OperationError);
return;
}
@@ -208,7 +208,7 @@ void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch,
WriteMode mode)
{
QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == Q_NULLPTR ||
+ if (controller == nullptr ||
(controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) ||
!contains(ch)) {
d_ptr->setError(QLowEnergyService::OperationError);
@@ -239,7 +239,7 @@ bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const
void QLowEnergyService::readDescriptor(const QLowEnergyDescriptor &descriptor)
{
QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) {
+ if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
d_ptr->setError(OperationError);
return;
}
@@ -251,7 +251,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
const QByteArray &newValue)
{
QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) {
+ if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
// This operation error also includes LE controller in the peripheral role:
// on iOS/OS X - descriptors are immutable.
d_ptr->setError(OperationError);
diff --git a/src/bluetooth/qlowenergyservicedata.h b/src/bluetooth/qlowenergyservicedata.h
index 48f7fe89..4d553267 100644
--- a/src/bluetooth/qlowenergyservicedata.h
+++ b/src/bluetooth/qlowenergyservicedata.h
@@ -40,7 +40,7 @@
#ifndef QLOWENERGYSERVICEDATA_H
#define QLOWENERGYSERVICEDATA_H
-#include <QtBluetooth/qbluetoothglobal.h>
+#include <QtBluetooth/qtbluetoothglobal.h>
#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qbluetoothglobal.h b/src/bluetooth/qtbluetoothglobal.h
index 45867e94..40b6d3d2 100644
--- a/src/bluetooth/qbluetoothglobal.h
+++ b/src/bluetooth/qtbluetoothglobal.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** 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.
diff --git a/src/bluetooth/qtbluetoothglobal_p.h b/src/bluetooth/qtbluetoothglobal_p.h
new file mode 100644
index 00000000..ffbfc4fe
--- /dev/null
+++ b/src/bluetooth/qtbluetoothglobal_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets 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 QTBLUETOOTHGLOBAL_P_H
+#define QTBLUETOOTHGLOBAL_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 <QtCore/private/qglobal_p.h>
+
+#include <QtBluetooth/qtbluetoothglobal.h>
+#include <QtBluetooth/private/qtbluetooth-config_p.h>
+
+#endif // QTBLUETOOTHGLOBAL_P_H
diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
index a3cfdcf2..0aa134f5 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
+++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h
@@ -60,7 +60,7 @@
#include <qbluetoothservicediscoveryagent.h>
#include <qbluetoothdevicediscoveryagent.h>
-#include <qbluetoothglobal.h>
+#include <qtbluetoothglobal.h>
#include "qdeclarativebluetoothservice_p.h"
diff --git a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
index a8b4a80f..0d5a5eae 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
+++ b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp
@@ -244,6 +244,7 @@ void QDeclarativeBluetoothSocket::setConnected(bool connected)
\li \c{ServiceNotFoundError}
\li \c{NetworkError}
\li \c{UnsupportedProtocolError}
+ \li \c{RemoteHostClosedError}
\endlist
The errors are derived from \l QBluetoothSocket::SocketError. This property is read-only.
@@ -297,7 +298,9 @@ void QDeclarativeBluetoothSocket::socket_state(QBluetoothSocket::SocketState sta
\li \c{Bound}
\endlist
- The states are derived from \l QBluetoothSocket::SocketState. This property is read-only.
+ The states (except \c{NoServiceSet}) are derived from \l QBluetoothSocket::SocketState. This property is read-only.
+ \c{NoServiceSet} indicates that the socket state is not yet available due to the \l service not being
+ set yet.
*/
QDeclarativeBluetoothSocket::SocketState QDeclarativeBluetoothSocket::state() const
{
diff --git a/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h b/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h
index faa2c29c..e5092d2c 100644
--- a/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h
+++ b/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h
@@ -78,6 +78,7 @@ public:
enum Error {
NoError = QBluetoothSocket::NoSocketError,
UnknownSocketError = QBluetoothSocket::UnknownSocketError,
+ RemoteHostClosedError = QBluetoothSocket::RemoteHostClosedError,
HostNotFoundError = QBluetoothSocket::HostNotFoundError,
ServiceNotFoundError = QBluetoothSocket::ServiceNotFoundError,
NetworkError = QBluetoothSocket::NetworkError,
diff --git a/src/nfc/doc/src/examples.qdoc b/src/nfc/doc/src/examples.qdoc
index 7216c03c..7fb3e758 100644
--- a/src/nfc/doc/src/examples.qdoc
+++ b/src/nfc/doc/src/examples.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
** 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.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/doc/src/nfc-android.qdoc b/src/nfc/doc/src/nfc-android.qdoc
index 7288b78a..d28f78ee 100644
--- a/src/nfc/doc/src/nfc-android.qdoc
+++ b/src/nfc/doc/src/nfc-android.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 BasysKom GmbH
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/doc/src/nfc-cpp.qdoc b/src/nfc/doc/src/nfc-cpp.qdoc
index f007dcf3..00fb8aa5 100644
--- a/src/nfc/doc/src/nfc-cpp.qdoc
+++ b/src/nfc/doc/src/nfc-cpp.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
** 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.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/doc/src/nfc-index.qdoc b/src/nfc/doc/src/nfc-index.qdoc
index a37ba293..c9acc92b 100644
--- a/src/nfc/doc/src/nfc-index.qdoc
+++ b/src/nfc/doc/src/nfc-index.qdoc
@@ -1,8 +1,8 @@
/****************************************************************************
**
** 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.
**
@@ -12,8 +12,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -21,7 +21,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/doc/src/nfc-overview.qdoc b/src/nfc/doc/src/nfc-overview.qdoc
index 9628ec49..6ac5c1dc 100644
--- a/src/nfc/doc/src/nfc-overview.qdoc
+++ b/src/nfc/doc/src/nfc-overview.qdoc
@@ -1,8 +1,8 @@
/****************************************************************************
**
** 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.
**
@@ -12,8 +12,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -21,7 +21,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/doc/src/nfc-qml.qdoc b/src/nfc/doc/src/nfc-qml.qdoc
index 3f96b39a..48df6d32 100644
--- a/src/nfc/doc/src/nfc-qml.qdoc
+++ b/src/nfc/doc/src/nfc-qml.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
** 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.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/nfc/nfc.pro b/src/nfc/nfc.pro
index d3053115..ae65640a 100644
--- a/src/nfc/nfc.pro
+++ b/src/nfc/nfc.pro
@@ -5,7 +5,7 @@ QMAKE_DOCS = $$PWD/doc/qtnfc.qdocconf
OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator
PUBLIC_HEADERS += \
- qnfcglobal.h \
+ qtnfcglobal.h \
qnearfieldmanager.h \
qnearfieldtarget.h \
qndefrecord.h \
@@ -19,6 +19,7 @@ PUBLIC_HEADERS += \
qnearfieldsharetarget.h
PRIVATE_HEADERS += \
+ qtnfcglobal_p.h \
qllcpsocket_p.h \
qllcpserver_p.h \
qndefrecord_p.h \
@@ -85,8 +86,6 @@ linux:!android:qtHaveModule(dbus) {
ANDROID_PERMISSIONS = \
android.permission.NFC
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
- jar/QtNfc-bundled.jar:org.qtproject.qt5.android.nfc.QtNfc
- ANDROID_JAR_DEPENDENCIES = \
jar/QtNfc.jar:org.qtproject.qt5.android.nfc.QtNfc
DEFINES += ANDROID_NFC
QT_PRIVATE += core-private gui androidextras
diff --git a/src/nfc/qllcpserver_p.h b/src/nfc/qllcpserver_p.h
index 5ff7b760..33ab6f1b 100644
--- a/src/nfc/qllcpserver_p.h
+++ b/src/nfc/qllcpserver_p.h
@@ -52,7 +52,7 @@
//
#include <QtCore/QObject>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include "qllcpsocket_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qllcpserver_p_p.h b/src/nfc/qllcpserver_p_p.h
index bd354d2b..62cfa953 100644
--- a/src/nfc/qllcpserver_p_p.h
+++ b/src/nfc/qllcpserver_p_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include "qllcpserver_p.h"
diff --git a/src/nfc/qllcpsocket_p.h b/src/nfc/qllcpsocket_p.h
index 18c3bf17..442367c6 100644
--- a/src/nfc/qllcpsocket_p.h
+++ b/src/nfc/qllcpsocket_p.h
@@ -53,7 +53,7 @@
#include <QtCore/QIODevice>
#include <QtNetwork/QAbstractSocket>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qllcpsocket_p_p.h b/src/nfc/qllcpsocket_p_p.h
index a15adcfe..9a747502 100644
--- a/src/nfc/qllcpsocket_p_p.h
+++ b/src/nfc/qllcpsocket_p_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include "qllcpsocket_p.h"
diff --git a/src/nfc/qndeffilter.h b/src/nfc/qndeffilter.h
index c1eaafd5..26327067 100644
--- a/src/nfc/qndeffilter.h
+++ b/src/nfc/qndeffilter.h
@@ -41,7 +41,7 @@
#define QNDEFFILTER_H
#include <QtCore/QSharedDataPointer>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNdefRecord>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qndefmessage.h b/src/nfc/qndefmessage.h
index 9bd4485b..59dedaa8 100644
--- a/src/nfc/qndefmessage.h
+++ b/src/nfc/qndefmessage.h
@@ -44,7 +44,7 @@
#include <QtCore/QSet>
#include <QtCore/QList>
#include <QtCore/QMetaType>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNdefRecord>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qndefnfcsmartposterrecord.cpp b/src/nfc/qndefnfcsmartposterrecord.cpp
index bc369980..73f2cd21 100644
--- a/src/nfc/qndefnfcsmartposterrecord.cpp
+++ b/src/nfc/qndefnfcsmartposterrecord.cpp
@@ -141,12 +141,10 @@ void QNdefNfcSmartPosterRecord::setPayload(const QByteArray &payload)
if (!payload.isEmpty()) {
// Create new structure
- QNdefMessage message = QNdefMessage::fromByteArray(payload);
+ const QNdefMessage message = QNdefMessage::fromByteArray(payload);
// Iterate through all the records contained in the payload's message.
- for (QList<QNdefRecord>::const_iterator iter = message.begin(); iter != message.end(); iter++) {
- QNdefRecord record = *iter;
-
+ for (const QNdefRecord& record : message) {
// Title
if (record.isRecordType<QNdefNfcTextRecord>()) {
addTitleInternal(record);
@@ -720,7 +718,7 @@ QNdefNfcSmartPosterRecord::Action QNdefNfcActRecord::action() const
QNdefNfcSmartPosterRecord::UnspecifiedAction;
if (!p.isEmpty())
- value = QNdefNfcSmartPosterRecord::Action(p[0]);
+ value = QNdefNfcSmartPosterRecord::Action(static_cast<signed char>(p[0]));
return value;
}
diff --git a/src/nfc/qndefnfcsmartposterrecord.h b/src/nfc/qndefnfcsmartposterrecord.h
index cf1bc623..9b714d5d 100644
--- a/src/nfc/qndefnfcsmartposterrecord.h
+++ b/src/nfc/qndefnfcsmartposterrecord.h
@@ -41,7 +41,7 @@
#define QNDEFNFCSMARTPOSTERRECORD_H
#include <QtCore/QList>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNdefRecord>
#include <QtNfc/qndefnfctextrecord.h>
#include <QtNfc/qndefnfcurirecord.h>
diff --git a/src/nfc/qndefnfctextrecord.h b/src/nfc/qndefnfctextrecord.h
index a7a3df42..72fc4878 100644
--- a/src/nfc/qndefnfctextrecord.h
+++ b/src/nfc/qndefnfctextrecord.h
@@ -40,7 +40,7 @@
#ifndef QNDEFNFCTEXTRECORD_H
#define QNDEFNFCTEXTRECORD_H
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNdefRecord>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qndefnfcurirecord.h b/src/nfc/qndefnfcurirecord.h
index 600f0f29..90a199a3 100644
--- a/src/nfc/qndefnfcurirecord.h
+++ b/src/nfc/qndefnfcurirecord.h
@@ -40,7 +40,7 @@
#ifndef QNDEFNFCURIRECORD_H
#define QNDEFNFCURIRECORD_H
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNdefRecord>
QT_FORWARD_DECLARE_CLASS(QUrl)
diff --git a/src/nfc/qndefrecord.h b/src/nfc/qndefrecord.h
index 2fd997d6..6cb6ac8c 100644
--- a/src/nfc/qndefrecord.h
+++ b/src/nfc/qndefrecord.h
@@ -42,7 +42,7 @@
#include <QtCore/QSharedDataPointer>
#include <QtCore/QByteArray>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qndefrecord_p.h b/src/nfc/qndefrecord_p.h
index 0a3d762d..89ce5d99 100644
--- a/src/nfc/qndefrecord_p.h
+++ b/src/nfc/qndefrecord_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include <QtCore/QSharedData>
#include <QtCore/QByteArray>
diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h
index 2cf69823..9583e01f 100644
--- a/src/nfc/qnearfieldmanager.h
+++ b/src/nfc/qnearfieldmanager.h
@@ -41,7 +41,7 @@
#define QNEARFIELDMANAGER_H
#include <QtCore/QObject>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
#include <QtNfc/QNearFieldTarget>
#include <QtNfc/QNdefRecord>
#include <QtNfc/QNdefFilter>
@@ -65,8 +65,8 @@ public:
Q_ENUM(TargetAccessMode)
Q_DECLARE_FLAGS(TargetAccessModes, TargetAccessMode)
- explicit QNearFieldManager(QObject *parent = Q_NULLPTR);
- explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = Q_NULLPTR);
+ explicit QNearFieldManager(QObject *parent = nullptr);
+ explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = nullptr);
~QNearFieldManager();
bool isAvailable() const;
diff --git a/src/nfc/qnearfieldmanager_p.h b/src/nfc/qnearfieldmanager_p.h
index 4cff375c..7e461da8 100644
--- a/src/nfc/qnearfieldmanager_p.h
+++ b/src/nfc/qnearfieldmanager_p.h
@@ -55,7 +55,7 @@
#include "qnearfieldtarget.h"
#include "qndefrecord.h"
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include <QtCore/QObject>
diff --git a/src/nfc/qnearfieldsharemanager.h b/src/nfc/qnearfieldsharemanager.h
index 5b76b84b..e34e9a64 100644
--- a/src/nfc/qnearfieldsharemanager.h
+++ b/src/nfc/qnearfieldsharemanager.h
@@ -41,7 +41,7 @@
#define QNEARFIELDSHAREMANAGER_H
#include <QtCore/QObject>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +53,7 @@ class Q_NFC_EXPORT QNearFieldShareManager : public QObject
Q_OBJECT
public:
- explicit QNearFieldShareManager(QObject *parent = Q_NULLPTR);
+ explicit QNearFieldShareManager(QObject *parent = nullptr);
~QNearFieldShareManager();
enum ShareError {
diff --git a/src/nfc/qnearfieldsharetarget.h b/src/nfc/qnearfieldsharetarget.h
index bde5e8b7..441ffda7 100644
--- a/src/nfc/qnearfieldsharetarget.h
+++ b/src/nfc/qnearfieldsharetarget.h
@@ -69,7 +69,7 @@ Q_SIGNALS:
void shareFinished();
private:
- explicit QNearFieldShareTarget(QNearFieldShareManager::ShareModes modes, QObject *parent = Q_NULLPTR);
+ explicit QNearFieldShareTarget(QNearFieldShareManager::ShareModes modes, QObject *parent = nullptr);
QNearFieldShareTargetPrivate *d_ptr;
Q_DECLARE_PRIVATE(QNearFieldShareTarget)
diff --git a/src/nfc/qnearfieldtagtype1.cpp b/src/nfc/qnearfieldtagtype1.cpp
index 5d46b8c5..34f2c8b8 100644
--- a/src/nfc/qnearfieldtagtype1.cpp
+++ b/src/nfc/qnearfieldtagtype1.cpp
@@ -174,7 +174,7 @@ void QNearFieldTagType1Private::progressToNextNdefReadMessageState()
delete m_tlvReader;
m_tlvReader = new QTlvReader(q);
- // fall through
+ Q_FALLTHROUGH(); // fall through
}
case NdefReadReadingTlv:
Q_ASSERT(m_tlvReader);
@@ -252,7 +252,7 @@ void QNearFieldTagType1Private::progressToNextNdefWriteMessageState()
delete m_tlvReader;
m_tlvReader = new QTlvReader(q);
- // fall through
+ Q_FALLTHROUGH(); // fall through
}
case NdefWriteReadingTlv:
Q_ASSERT(m_tlvReader);
diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h
index 641645c3..e51960f7 100644
--- a/src/nfc/qnearfieldtarget.h
+++ b/src/nfc/qnearfieldtarget.h
@@ -45,7 +45,7 @@
#include <QtCore/QMetaType>
#include <QtCore/QObject>
#include <QtCore/QSharedDataPointer>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_BEGIN_NAMESPACE
class QString;
@@ -118,7 +118,7 @@ public:
QSharedDataPointer<RequestIdPrivate> d;
};
- explicit QNearFieldTarget(QObject *parent = Q_NULLPTR);
+ explicit QNearFieldTarget(QObject *parent = nullptr);
virtual ~QNearFieldTarget();
virtual QByteArray uid() const = 0;
diff --git a/src/nfc/qnearfieldtarget_p.h b/src/nfc/qnearfieldtarget_p.h
index 9cef2f55..9c1a2954 100644
--- a/src/nfc/qnearfieldtarget_p.h
+++ b/src/nfc/qnearfieldtarget_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include "qnearfieldtarget.h"
diff --git a/src/nfc/qnfc.cpp b/src/nfc/qnfc.cpp
index b754b8d7..56a4f4f3 100644
--- a/src/nfc/qnfc.cpp
+++ b/src/nfc/qnfc.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include <QtCore/QLoggingCategory>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/nfc/qqmlndefrecord.h b/src/nfc/qqmlndefrecord.h
index 9e8d8bbd..0f624505 100644
--- a/src/nfc/qqmlndefrecord.h
+++ b/src/nfc/qqmlndefrecord.h
@@ -69,8 +69,8 @@ public:
};
Q_ENUM(TypeNameFormat)
- explicit QQmlNdefRecord(QObject *parent = Q_NULLPTR);
- explicit QQmlNdefRecord(const QNdefRecord &record, QObject *parent = Q_NULLPTR);
+ explicit QQmlNdefRecord(QObject *parent = nullptr);
+ explicit QQmlNdefRecord(const QNdefRecord &record, QObject *parent = nullptr);
~QQmlNdefRecord();
QString type() const;
diff --git a/src/nfc/qtlv_p.h b/src/nfc/qtlv_p.h
index 43e78c5c..1a4c6def 100644
--- a/src/nfc/qtlv_p.h
+++ b/src/nfc/qtlv_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qnfcglobal.h"
+#include "qtnfcglobal.h"
#include "qnearfieldtarget.h"
diff --git a/src/nfc/qnfcglobal.h b/src/nfc/qtnfcglobal.h
index 80a8cfa4..2a1e40b4 100644
--- a/src/nfc/qnfcglobal.h
+++ b/src/nfc/qtnfcglobal.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNfc module of the Qt Toolkit.
diff --git a/src/nfc/qtnfcglobal_p.h b/src/nfc/qtnfcglobal_p.h
new file mode 100644
index 00000000..2f40d464
--- /dev/null
+++ b/src/nfc/qtnfcglobal_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets 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 QTNFCGLOBAL_P_H
+#define QTNFCGLOBAL_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 <QtCore/private/qglobal_p.h>
+
+#include <QtNfc/qtnfcglobal.h>
+#include <QtNfc/private/qtnfc-config_p.h>
+
+#endif // QTNFCGLOBAL_P_H
diff --git a/src/nfc/targetemulator_p.h b/src/nfc/targetemulator_p.h
index 1233207f..1f682704 100644
--- a/src/nfc/targetemulator_p.h
+++ b/src/nfc/targetemulator_p.h
@@ -53,7 +53,7 @@
#include <QtCore/QtGlobal>
#include <QtCore/QByteArray>
-#include <QtNfc/qnfcglobal.h>
+#include <QtNfc/qtnfcglobal.h>
QT_FORWARD_DECLARE_CLASS(QSettings)
diff --git a/src/tools/sdpscanner/qt_attribution.json b/src/tools/sdpscanner/qt_attribution.json
index 9f2ada92..cf0e5136 100644
--- a/src/tools/sdpscanner/qt_attribution.json
+++ b/src/tools/sdpscanner/qt_attribution.json
@@ -2,11 +2,15 @@
"Id": "bluez",
"Name": "BlueZ",
"QDocModule": "qtbluetooth",
- "QtUsage": "On Linux, Qt Bluetooth uses a separate executable, sdpscanner, to integrate with the official Linux bluetooth protocol stack BlueZ. The Qt Bluetooth library does not link against BlueZ directly.",
-
- "Description": "BlueZ",
+ "QtUsage": "On Linux, Qt Bluetooth uses a separate executable, sdpscanner,
+to integrate with the official Linux Bluetooth protocol stack (BlueZ). The usage is limited
+to service discovery via SDP. The Qt Bluetooth library itself does NOT link against BlueZ.
+Communication between sdpscanner and QtBluetooth happens via stdin/stdout. Therefore
+QtBluetooth and user code linking to it is not considered a derivative work, and does not
+have to be released under GPL too.",
+ "Description": "SDP Search via BlueZ",
"Homepage": "http://www.bluez.org/",
"LicenseId": "GPL-2.0",
- "License": "GNU General Public License v2.0 only",
+ "License": "GNU General Public License v2.0 only (This does not force user code to be GPL'ed. For more info see details.)",
"Copyright": "Copyright (C) 2000-2016 BlueZ Project."
}