summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/qlowenergycontroller.cpp5
8 files changed, 99 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 deb70dc0..9fe88e9c 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
@@ -114,11 +114,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/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index c152ded2..6581c4ad 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -813,7 +813,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.