summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java4
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver_p.h4
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp85
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver_p.h5
-rw-r--r--src/bluetooth/android/jni_android.cpp8
-rw-r--r--src/bluetooth/android/localdevicebroadcastreceiver_p.h2
-rw-r--r--src/bluetooth/android/servicediscoverybroadcastreceiver_p.h2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp8
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp22
-rw-r--r--src/bluetooth/qlowenergycontroller.h1
-rw-r--r--src/bluetooth/qlowenergycontroller_osx.mm7
-rw-r--r--src/nfc/nfc.pro1
-rw-r--r--src/nfc/qllcpserver.cpp2
13 files changed, 135 insertions, 16 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
index faf45621..481f2917 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
@@ -115,11 +115,11 @@ public class QtBluetoothLE {
if (qtObject == 0)
return;
- leScanResult(qtObject, device, rssi);
+ leScanResult(qtObject, device, rssi, scanRecord);
}
};
- public native void leScanResult(long qtObject, BluetoothDevice device, int rssi);
+ public native void leScanResult(long qtObject, BluetoothDevice device, int rssi, byte[] scanRecord);
/*************************************************************/
/* Service Discovery */
diff --git a/src/bluetooth/android/androidbroadcastreceiver_p.h b/src/bluetooth/android/androidbroadcastreceiver_p.h
index 01d57992..ed30acad 100644
--- a/src/bluetooth/android/androidbroadcastreceiver_p.h
+++ b/src/bluetooth/android/androidbroadcastreceiver_p.h
@@ -75,8 +75,8 @@ public:
protected:
friend void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, jobject, jobject);
virtual void onReceive(JNIEnv *env, jobject context, jobject intent) = 0;
- friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject, jint);
- virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi) = 0;
+ friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject, jint, jbyteArray);
+ virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord) = 0;
QAndroidJniObject contextObject;
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index a246889f..c807df7f 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -39,13 +39,16 @@
****************************************************************************/
#include "android/devicediscoverybroadcastreceiver_p.h"
+#include <QtCore/QtEndian>
#include <QtCore/QLoggingCategory>
#include <QtBluetooth/QBluetoothAddress>
#include <QtBluetooth/QBluetoothDeviceInfo>
+#include <QtBluetooth/QBluetoothUuid>
#include "android/jni_android_p.h"
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/QHash>
#include <QtCore/qbitarray.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -234,6 +237,27 @@ static const MinorClassJavaToQtMapping minorMappings[] = {
{ Q_NULLPTR, 0 }, // index 64 & separator
};
+/*! Advertising Data Type (AD type) for LE scan records, as defined in Bluetooth CSS v6. */
+enum ADType {
+ ADType16BitUuidIncomplete = 0x02,
+ ADType16BitUuidComplete = 0x03,
+ ADType32BitUuidIncomplete = 0x04,
+ ADType32BitUuidComplete = 0x05,
+ ADType128BitUuidIncomplete = 0x06,
+ ADType128BitUuidComplete = 0x07,
+ // .. more will be added when required
+};
+
+// Endianness conversion for quint128 doesn't (yet) exist in qtendian.h
+template <>
+inline quint128 qbswap<quint128>(const quint128 src)
+{
+ quint128 dst;
+ for (int i = 0; i < 16; i++)
+ dst.data[i] = src.data[15 - i];
+ return dst;
+}
+
QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType)
{
const JCachedBtTypes::iterator it = cachedBtTypes()->find(javaType);
@@ -425,19 +449,18 @@ void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, j
// Runs in Java thread
void DeviceDiscoveryBroadcastReceiver::onReceiveLeScan(
- JNIEnv *env, jobject jBluetoothDevice, jint rssi)
+ JNIEnv *env, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord)
{
- qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceiveLeScan()";
const QAndroidJniObject bluetoothDevice(jBluetoothDevice);
if (!bluetoothDevice.isValid())
return;
- const QBluetoothDeviceInfo info = retrieveDeviceInfo(env, bluetoothDevice, rssi);
+ const QBluetoothDeviceInfo info = retrieveDeviceInfo(env, bluetoothDevice, rssi, scanRecord);
if (info.isValid())
emit deviceDiscovered(info, true);
}
-QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv *env, const QAndroidJniObject &bluetoothDevice, int rssi)
+QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv *env, const QAndroidJniObject &bluetoothDevice, int rssi, jbyteArray scanRecord)
{
const QString deviceName = bluetoothDevice.callObjectMethod<jstring>("getName").toString();
const QBluetoothAddress deviceAddress(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString());
@@ -485,6 +508,60 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv
QBluetoothDeviceInfo info(deviceAddress, deviceName, classType);
info.setRssi(rssi);
+ if (scanRecord != nullptr) {
+ // Parse scan record
+ jboolean isCopy;
+ const char *scanRecordBuffer = reinterpret_cast<const char *>(env->GetByteArrayElements(scanRecord, &isCopy));
+ const int scanRecordLength = env->GetArrayLength(scanRecord);
+
+ QList<QBluetoothUuid> serviceUuids;
+ int i = 0;
+
+ // Spec 4.2, Vol 3, Part C, Chapter 11
+ while (i < scanRecordLength) {
+ // sizeof(EIR Data) = sizeof(Length) + sizeof(EIR data Type) + sizeof(EIR Data)
+ // Length = sizeof(EIR data Type) + sizeof(EIR Data)
+
+ const int nBytes = scanRecordBuffer[i];
+ if (nBytes == 0)
+ break;
+
+ if ((i + nBytes) >= scanRecordLength)
+ break;
+
+ const int adType = scanRecordBuffer[i+1];
+ const char *dataPtr = &scanRecordBuffer[i+2];
+ QBluetoothUuid foundService;
+
+ switch (adType) {
+ case ADType16BitUuidIncomplete:
+ case ADType16BitUuidComplete:
+ foundService = QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr));
+ break;
+ case ADType32BitUuidIncomplete:
+ case ADType32BitUuidComplete:
+ foundService = QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr));
+ break;
+ case ADType128BitUuidIncomplete:
+ case ADType128BitUuidComplete:
+ foundService =
+ QBluetoothUuid(qToBigEndian<quint128>(qFromLittleEndian<quint128>(dataPtr)));
+ break;
+ default:
+ // no other types supported yet and therefore skipped
+ // https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
+ break;
+ }
+
+ i += nBytes + 1;
+
+ if (!foundService.isNull() && !serviceUuids.contains(foundService))
+ serviceUuids.append(foundService);
+ }
+
+ info.setServiceUuids(serviceUuids, QBluetoothDeviceInfo::DataIncomplete);
+ }
+
if (QtAndroidPrivate::androidSdkVersion() >= 18) {
jint javaBtType = bluetoothDevice.callMethod<jint>("getType");
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h
index 835a7654..526c57e2 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h
@@ -65,7 +65,8 @@ class DeviceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver
public:
DeviceDiscoveryBroadcastReceiver(QObject* parent = 0);
virtual void onReceive(JNIEnv *env, jobject context, jobject intent);
- virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi);
+ virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi,
+ jbyteArray scanRecord);
signals:
void deviceDiscovered(const QBluetoothDeviceInfo &info, bool isLeScanResult);
@@ -73,7 +74,7 @@ signals:
private:
QBluetoothDeviceInfo retrieveDeviceInfo(JNIEnv *env, const QAndroidJniObject& bluetoothDevice,
- int rssi);
+ int rssi, jbyteArray scanRecord = nullptr);
};
QT_END_NAMESPACE
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp
index 95011c6c..ae07608a 100644
--- a/src/bluetooth/android/jni_android.cpp
+++ b/src/bluetooth/android/jni_android.cpp
@@ -190,10 +190,12 @@ static void QtBluetoothInputStreamThread_readyData(JNIEnv */*env*/, jobject /*ja
reinterpret_cast<InputStreamThread*>(qtObject)->javaReadyRead(buffer, bufferLength);
}
-void QtBluetoothLE_leScanResult(JNIEnv *env, jobject, jlong qtObject, jobject bluetoothDevice, jint rssi)
+void QtBluetoothLE_leScanResult(JNIEnv *env, jobject, jlong qtObject, jobject bluetoothDevice,
+ jint rssi, jbyteArray scanRecord)
{
reinterpret_cast<AndroidBroadcastReceiver*>(qtObject)->onReceiveLeScan(
- env, bluetoothDevice, rssi);
+ env, bluetoothDevice, rssi,
+ scanRecord);
}
@@ -203,7 +205,7 @@ static JNINativeMethod methods[] = {
};
static JNINativeMethod methods_le[] = {
- {"leScanResult", "(JLandroid/bluetooth/BluetoothDevice;I)V",
+ {"leScanResult", "(JLandroid/bluetooth/BluetoothDevice;I[B)V",
(void *) QtBluetoothLE_leScanResult},
{"leConnectionStateChange", "(JII)V",
(void *) LowEnergyNotificationHub::lowEnergy_connectionChange},
diff --git a/src/bluetooth/android/localdevicebroadcastreceiver_p.h b/src/bluetooth/android/localdevicebroadcastreceiver_p.h
index 90f40333..261bf29d 100644
--- a/src/bluetooth/android/localdevicebroadcastreceiver_p.h
+++ b/src/bluetooth/android/localdevicebroadcastreceiver_p.h
@@ -64,7 +64,7 @@ public:
explicit LocalDeviceBroadcastReceiver(QObject *parent = 0);
virtual ~LocalDeviceBroadcastReceiver() {}
virtual void onReceive(JNIEnv *env, jobject context, jobject intent);
- virtual void onReceiveLeScan(JNIEnv *, jobject, jint) {}
+ virtual void onReceiveLeScan(JNIEnv *, jobject, jint, jbyteArray) {}
bool pairingConfirmation(bool accept);
signals:
diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h
index f0abf511..a93cbd3f 100644
--- a/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h
+++ b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h
@@ -66,7 +66,7 @@ class ServiceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver
public:
ServiceDiscoveryBroadcastReceiver(QObject* parent = 0);
virtual void onReceive(JNIEnv *env, jobject context, jobject intent);
- virtual void onReceiveLeScan(JNIEnv *, jobject, jint) {}
+ virtual void onReceiveLeScan(JNIEnv *, jobject, jint, jbyteArray) {}
static QList<QBluetoothUuid> convertParcelableArray(const QAndroidJniObject &obj);
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 411e7a2b..2d6e64be 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -69,9 +69,17 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
lowEnergySearchTimeout(25000),
q_ptr(parent)
{
+ QAndroidJniEnvironment env;
adapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
"getDefaultAdapter",
"()Landroid/bluetooth/BluetoothAdapter;");
+ if (!adapter.isValid()) {
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
+ }
}
QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 2b28a873..4df92a39 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -635,6 +635,23 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const
}
/*!
+ Returns the unique identifier of the remote Bluetooth Low Energy device.
+
+ On macOS/iOS/tvOS CoreBluetooth does not expose/accept hardware addresses for
+ LE devices; instead developers are supposed to use unique 128-bit UUIDs, generated
+ by CoreBluetooth. These UUIDS will stay constant for the same central <-> peripheral
+ pair and we use them when connecting to a remote device. For a controller in the
+ \l CentralRole, this value will always be the one passed in when the controller
+ object was created. For a controller in the \l PeripheralRole, this value is invalid.
+
+ \since 5.8
+ */
+QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
+{
+ return QBluetoothUuid();
+}
+
+/*!
Returns the name of the remote Bluetooth Low Energy device, if the controller is in the
\l CentralRole. Otherwise the result is unspecified.
@@ -825,7 +842,10 @@ QLowEnergyService *QLowEnergyController::createServiceObject(
also starts listening for incoming client connections.
Providing \a scanResponseData is not required, as it is not applicable for certain
- configurations of \c parameters.
+ configurations of \c parameters. \a advertisingData and \a scanResponseData are limited
+ to 31 byte user data. If, for example, several 128bit uuids are added to \a advertisingData,
+ the advertised packets may not contain all uuids. The existing limit may have caused the truncation
+ of uuids. In such cases \a scanResponseData may be used for additional information.
If this object is currently not in the \l UnconnectedState, nothing happens.
\note Advertising will stop automatically once a client connects to the local device.
diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h
index 4ee07531..1c4fa83f 100644
--- a/src/bluetooth/qlowenergycontroller.h
+++ b/src/bluetooth/qlowenergycontroller.h
@@ -107,6 +107,7 @@ public:
QBluetoothAddress localAddress() const;
QBluetoothAddress remoteAddress() const;
+ QBluetoothUuid remoteDeviceUuid() const;
QString remoteName() const;
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm
index f2b7b0bd..80ef72af 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_osx.mm
@@ -1098,6 +1098,13 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const
return osx_d_ptr->remoteAddress;
}
+QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
+{
+ OSX_D_PTR;
+
+ return osx_d_ptr->deviceUuid;
+}
+
QString QLowEnergyController::remoteName() const
{
OSX_D_PTR;
diff --git a/src/nfc/nfc.pro b/src/nfc/nfc.pro
index 8e737dd5..0819cc4f 100644
--- a/src/nfc/nfc.pro
+++ b/src/nfc/nfc.pro
@@ -80,6 +80,7 @@ linux:!android:qtHaveModule(dbus) {
} else:android {
NFC_BACKEND_AVAILABLE = yes
+ DEFINES += QT_ANDROID_NFC
ANDROID_PERMISSIONS = \
android.permission.NFC
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
diff --git a/src/nfc/qllcpserver.cpp b/src/nfc/qllcpserver.cpp
index 2bf2a097..66831b9f 100644
--- a/src/nfc/qllcpserver.cpp
+++ b/src/nfc/qllcpserver.cpp
@@ -41,6 +41,8 @@
#if defined(QT_SIMULATOR)
#include "qllcpserver_simulator_p.h"
+#elif defined(QT_ANDROID_NFC)
+#include "qllcpserver_android_p.h"
#else
#include "qllcpserver_p_p.h"
#endif