summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2014-11-07 15:51:02 +0100
committerAlex Blasche <alexander.blasche@theqtcompany.com>2014-11-11 09:14:55 +0100
commita57a9a6598eb8fa2578ea8511b351b49d5b55ff0 (patch)
tree2b357b3aad43cfeaf14713a4d0c2900582d23c81
parent327b6b7f8ff9acda74f403f2ff286e67f4202dfd (diff)
The service->characteristic->descriptor tree becomes available in Qt
At the same time this fixes bugs the following bugs: 1.) Non-readable characteristics were not visible 2.) Crashes when descriptor/characteristic values were empty 3.) QLEService::discoverServiceDetails always finished with an UnknownError Missing/incorrect are still service details such as included services and the service type (which currently always defaults to primary service). Change-Id: Id73013a3784cd3c3f632102f13f5459ab37e95a6 Reviewed-by: Timur Pocheptsov <Timur.Pocheptsov@digia.com> Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java182
-rw-r--r--src/bluetooth/android/jni_android.cpp4
-rw-r--r--src/bluetooth/android/lowenergynotificationhub.cpp72
-rw-r--r--src/bluetooth/android/lowenergynotificationhub_p.h13
-rw-r--r--src/bluetooth/qlowenergycontroller_android.cpp50
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h5
6 files changed, 281 insertions, 45 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 93b4a50d..9295c2bb 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
@@ -45,7 +45,6 @@ import android.bluetooth.BluetoothProfile;
import android.util.Log;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
@@ -165,18 +164,66 @@ public class QtBluetoothLE {
android.bluetooth.BluetoothGattCharacteristic characteristic,
int status)
{
+ if (status != BluetoothGatt.GATT_SUCCESS) {
+ Log.w(TAG, "onCharacteristicRead error: " + status);
+ return;
+ }
+
+ //runningHandle is only used during serviceDetailsDiscovery
+ //If it is -1 we got an update outside of the details discovery process
+ if (runningHandle == -1) {
+ List<Integer> handles = uuidToEntry.get(characteristic.getService().getUuid());
+ if (handles == null || handles.isEmpty()) {
+ Log.w(TAG, "Received Characteristic read update for unknown characteristic");
+ return;
+ }
+ int serviceHandle = handles.get(0);
+ GattEntry entry;
+ int foundHandle = -1;
+ try {
+ for (int i = 1; serviceHandle + i < entries.size() && foundHandle == -1; i++) {
+ entry = entries.get(serviceHandle + i);
+ if (entry == null)
+ continue;
+
+ if (entry.type == GattEntryType.Service) {
+ Log.w(TAG, "Out-of-detail-discovery: found unknown characteristic for known service");
+ break; //reached next service -> unknown characteristic in service
+ }
+
+ if (entry.type != GattEntryType.Characteristic)
+ continue;
+
+ if (entry.characteristic == characteristic)
+ foundHandle = serviceHandle + i;
+ }
+ } catch (IndexOutOfBoundsException ex) {
+ Log.w(TAG, "Out-of-detail-discovery: cannot find handle for characteristic");
+ return;
+ }
+
+ if (foundHandle == -1) {
+ Log.w(TAG, "Out-of-detail-discovery: char update failed");
+ return;
+ }
+
+ leCharacteristicRead(qtObject, characteristic.getService().getUuid().toString(),
+ foundHandle+1, characteristic.getUuid().toString(),
+ characteristic.getProperties(), characteristic.getValue());
+
+ return;
+ }
+
GattEntry entry = entries.get(runningHandle);
entry.valueKnown = true;
entries.set(runningHandle, entry);
- String data = new String(characteristic.getValue());
- // Qt manages handles starting at 1, in Java we use a system starting with 0
- characteristic.getService().getUuid().toString();
+ // Qt manages handles starting at 1, in Java we use a system starting with 0
//TODO avoid sending service uuid -> service handle should be sufficient
leCharacteristicRead(qtObject, characteristic.getService().getUuid().toString(),
- runningHandle+1, characteristic.getUuid().toString(),
+ runningHandle + 1, characteristic.getUuid().toString(),
characteristic.getProperties(), characteristic.getValue());
- performServiceDiscoveryForHandle(runningHandle+1, false);
+ performServiceDetailDiscoveryForHandle(runningHandle + 1, false);
}
public void onCharacteristicWrite(android.bluetooth.BluetoothGatt gatt,
@@ -196,10 +243,63 @@ public class QtBluetoothLE {
android.bluetooth.BluetoothGattDescriptor descriptor,
int status)
{
+ if (status != BluetoothGatt.GATT_SUCCESS) {
+ Log.w(TAG, "onDescriptorRead error: " + status);
+ return;
+ }
+
+ //runningHandle is only used during serviceDetailsDiscovery
+ //If it is -1 we got an update outside of the details discovery process
+ if (runningHandle == -1) {
+ List<Integer> handles = uuidToEntry.get(descriptor.getCharacteristic().getService().getUuid());
+ if (handles == null || handles.isEmpty()) {
+ Log.w(TAG, "Received Descriptor read update for unknown descriptor");
+ return;
+ }
+
+ int serviceHandle = handles.get(0);
+ GattEntry entry;
+ int foundHandle = -1;
+ try {
+ for (int i = 1; serviceHandle + i < entries.size() && foundHandle == -1; i++) {
+ entry = entries.get(serviceHandle + i);
+ if (entry == null)
+ continue;
+
+ if (entry.type == GattEntryType.Service) {
+ Log.w(TAG, "Out-of-detail-discovery: found unknown descriptor for known service");
+ break; //reached next service -> unknown descriptor in service
+ }
+
+ if (entry.type != GattEntryType.Descriptor)
+ continue;
+
+ if (entry.descriptor == descriptor)
+ foundHandle = serviceHandle + i;
+ }
+ } catch (IndexOutOfBoundsException ex) {
+ Log.w(TAG, "Out-of-detail-discovery: cannot find handle for descriptor");
+ return;
+ }
+
+ if (foundHandle == -1)
+ Log.w(TAG, "Out-of-detail-discovery: char update failed");
+
+ leDescriptorRead(qtObject, descriptor.getCharacteristic().getService().getUuid().toString(),
+ descriptor.getCharacteristic().getUuid().toString(), foundHandle+1,
+ descriptor.getUuid().toString(), descriptor.getValue());
+ return;
+ }
+
+
GattEntry entry = entries.get(runningHandle);
entry.valueKnown = true;
entries.set(runningHandle, entry);
- performServiceDiscoveryForHandle(runningHandle+1, false);
+ //TODO avoid sending service and characteristic uuid -> handles should be sufficient
+ leDescriptorRead(qtObject, descriptor.getCharacteristic().getService().getUuid().toString(),
+ descriptor.getCharacteristic().getUuid().toString(), runningHandle+1,
+ descriptor.getUuid().toString(), descriptor.getValue());
+ performServiceDetailDiscoveryForHandle(runningHandle + 1, false);
}
public void onDescriptorWrite(android.bluetooth.BluetoothGatt gatt,
@@ -263,6 +363,7 @@ public class QtBluetoothLE {
public BluetoothGattService service = null;
public BluetoothGattCharacteristic characteristic = null;
public BluetoothGattDescriptor descriptor = null;
+ public int endHandle;
}
Hashtable<UUID, List<Integer>> uuidToEntry = new Hashtable<UUID, List<Integer>>(100);
ArrayList<GattEntry> entries = new ArrayList<GattEntry>(100);
@@ -275,11 +376,14 @@ public class QtBluetoothLE {
GattEntry entry = null;
List<BluetoothGattService> services = mBluetoothGatt.getServices();
for (BluetoothGattService service: services) {
- entry = new GattEntry();
- entry.type = GattEntryType.Service;
- entry.service = service;
+ GattEntry serviceEntry = new GattEntry();
+ serviceEntry.type = GattEntryType.Service;
+ serviceEntry.service = service;
entries.add(entry);
+ // remember handle for the service for later update
+ int serviceHandle = entries.size() - 1;
+
//some devices may have more than one service with the same uuid
List<Integer> old = uuidToEntry.get(service.getUuid());
if (old == null)
@@ -287,29 +391,32 @@ public class QtBluetoothLE {
old.add(entries.size()-1);
uuidToEntry.put(service.getUuid(), old);
+ // add all characteristics
List<BluetoothGattCharacteristic> charList = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic: charList) {
entry = new GattEntry();
entry.type = GattEntryType.Characteristic;
entry.characteristic = characteristic;
entries.add(entry);
- //uuidToEntry.put(characteristic.getUuid(), entries.size()-1);
// this emulates GATT value attributes
entry = new GattEntry();
entry.type = GattEntryType.CharacteristicValue;
entries.add(entry);
- //uuidToEntry.put(characteristic.getUuid(), entry);
+ // add all descriptors
List<BluetoothGattDescriptor> descList = characteristic.getDescriptors();
for (BluetoothGattDescriptor desc: descList) {
entry = new GattEntry();
entry.type = GattEntryType.Descriptor;
entry.descriptor = desc;
entries.add(entry);
- //uuidToEntry.put(desc.getUuid(), entries.size()-1);
}
}
+
+ // update endHandle of current service
+ serviceEntry.endHandle = entries.size() - 1;
+ entries.set(serviceHandle, serviceEntry);
}
entries.trimToSize();
@@ -364,7 +471,7 @@ public class QtBluetoothLE {
}
if (!entry.valueKnown) {
- performServiceDiscoveryForHandle(serviceHandle, true);
+ performServiceDetailDiscoveryForHandle(serviceHandle, true);
} else {
Log.w(TAG, "Service already discovered");
}
@@ -379,15 +486,19 @@ public class QtBluetoothLE {
private void finishCurrentServiceDiscovery()
{
+ int currentEntry = currentServiceInDiscovery;
GattEntry discoveredService = entries.get(currentServiceInDiscovery);
discoveredService.valueKnown = true;
entries.set(currentServiceInDiscovery, discoveredService);
+
runningHandle = -1;
currentServiceInDiscovery = -1;
- leServiceDetailDiscoveryFinished(qtObject, discoveredService.service.getUuid().toString());
+
+ leServiceDetailDiscoveryFinished(qtObject, discoveredService.service.getUuid().toString(),
+ currentEntry + 1, discoveredService.endHandle + 1);
}
- private synchronized void performServiceDiscoveryForHandle(int nextHandle, boolean searchStarted)
+ private synchronized void performServiceDetailDiscoveryForHandle(int nextHandle, boolean searchStarted)
{
try {
if (searchStarted) {
@@ -411,17 +522,40 @@ public class QtBluetoothLE {
switch (entry.type) {
case Characteristic:
result = mBluetoothGatt.readCharacteristic(entry.characteristic);
- if (!result)
- performServiceDiscoveryForHandle(runningHandle+1, false);
+ try {
+ if (!result) {
+ // add characteristic now since we won't get a read update later one
+ // this is possible when the characteristic is not readable
+ Log.d(TAG, "Non-readable characteristic " + entry.characteristic.getUuid() +
+ " for service " + entry.characteristic.getService().getUuid());
+ leCharacteristicRead(qtObject, entry.characteristic.getService().getUuid().toString(),
+ nextHandle + 1, entry.characteristic.getUuid().toString(),
+ entry.characteristic.getProperties(), entry.characteristic.getValue());
+ performServiceDetailDiscoveryForHandle(runningHandle + 1, false);
+ }
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
break;
case CharacteristicValue:
// ignore -> nothing to do for this artificial type
- performServiceDiscoveryForHandle(runningHandle+1, false);
+ performServiceDetailDiscoveryForHandle(runningHandle + 1, false);
break;
case Descriptor:
result = mBluetoothGatt.readDescriptor(entry.descriptor);
- if (!result)
- performServiceDiscoveryForHandle(runningHandle+1, false);
+ if (!result) {
+ // atm all descriptor types are readable
+ Log.d(TAG, "Non-readable descriptor " + entry.descriptor.getUuid() +
+ " for service/char" + entry.descriptor.getCharacteristic().getService().getUuid() +
+ "/" + entry.descriptor.getCharacteristic().getUuid());
+ leDescriptorRead(qtObject,
+ entry.descriptor.getCharacteristic().getService().getUuid().toString(),
+ entry.descriptor.getCharacteristic().getUuid().toString(),
+ nextHandle+1, entry.descriptor.getUuid().toString(),
+ entry.descriptor.getValue());
+ performServiceDetailDiscoveryForHandle(runningHandle + 1, false);
+ }
break;
case Service:
finishCurrentServiceDiscovery();
@@ -438,9 +572,13 @@ public class QtBluetoothLE {
public native void leConnectionStateChange(long qtObject, int wasErrorTransition, int newState);
public native void leServicesDiscovered(long qtObject, int errorCode, String uuidList);
- public native void leServiceDetailDiscoveryFinished(long qtObject, final String serviceUuid);
+ public native void leServiceDetailDiscoveryFinished(long qtObject, final String serviceUuid,
+ int startHandle, int endHandle);
public native void leCharacteristicRead(long qtObject, String serviceUuid,
int charHandle, String charUuid,
int properties, byte[] data);
+ public native void leDescriptorRead(long qtObject, String serviceUuid, String charUuid,
+ int descHandle, String descUuid, byte[] data);
+
}
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp
index b75ca2df..745a0c98 100644
--- a/src/bluetooth/android/jni_android.cpp
+++ b/src/bluetooth/android/jni_android.cpp
@@ -203,10 +203,12 @@ static JNINativeMethod methods_le[] = {
(void *) LowEnergyNotificationHub::lowEnergy_connectionChange},
{"leServicesDiscovered", "(JILjava/lang/String;)V",
(void *) LowEnergyNotificationHub::lowEnergy_servicesDiscovered},
- {"leServiceDetailDiscoveryFinished", "(JLjava/lang/String;)V",
+ {"leServiceDetailDiscoveryFinished", "(JLjava/lang/String;II)V",
(void *) LowEnergyNotificationHub::lowEnergy_serviceDetailsDiscovered},
{"leCharacteristicRead", "(JLjava/lang/String;ILjava/lang/String;I[B)V",
(void *) LowEnergyNotificationHub::lowEnergy_characteristicRead},
+ {"leDescriptorRead", "(JLjava/lang/String;Ljava/lang/String;ILjava/lang/String;[B)V",
+ (void *) LowEnergyNotificationHub::lowEnergy_descriptorRead},
};
static JNINativeMethod methods_server[] = {
diff --git a/src/bluetooth/android/lowenergynotificationhub.cpp b/src/bluetooth/android/lowenergynotificationhub.cpp
index 71aa5a02..709bbc68 100644
--- a/src/bluetooth/android/lowenergynotificationhub.cpp
+++ b/src/bluetooth/android/lowenergynotificationhub.cpp
@@ -123,7 +123,8 @@ void LowEnergyNotificationHub::lowEnergy_servicesDiscovered(
}
void LowEnergyNotificationHub::lowEnergy_serviceDetailsDiscovered(
- JNIEnv *, jobject, jlong qtObject, jobject uuid)
+ JNIEnv *, jobject, jlong qtObject, jobject uuid, jint startHandle,
+ jint endHandle)
{
lock.lockForRead();
LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
@@ -134,7 +135,9 @@ void LowEnergyNotificationHub::lowEnergy_serviceDetailsDiscovered(
const QString serviceUuid = QAndroidJniObject(uuid).toString();
QMetaObject::invokeMethod(hub, "serviceDetailsDiscoveryFinished",
Qt::QueuedConnection,
- Q_ARG(QString, serviceUuid));
+ Q_ARG(QString, serviceUuid),
+ Q_ARG(int, startHandle),
+ Q_ARG(int, endHandle));
}
void LowEnergyNotificationHub::lowEnergy_characteristicRead(
@@ -147,29 +150,74 @@ void LowEnergyNotificationHub::lowEnergy_characteristicRead(
if (!hub)
return;
-
const QBluetoothUuid serviceUuid(QAndroidJniObject(sUuid).toString());
if (serviceUuid.isNull())
return;
const QBluetoothUuid charUuid(QAndroidJniObject(cUuid).toString());
-
- jsize length = env->GetArrayLength(data);
- jbyte* nativeData = (jbyte*) malloc(length * sizeof(jbyte));
- if (!nativeData)
+ if (charUuid.isNull())
return;
- env->GetByteArrayRegion(data, 0, length, nativeData);
- const QByteArray qtArray(reinterpret_cast<const char*>(nativeData),
- length); //takes ownership of data
+ QByteArray payload;
+ if (data) { //empty Java byte array is 0x0
+ jsize length = env->GetArrayLength(data);
+ jbyte* nativeData = (jbyte*) malloc(length * sizeof(jbyte));
+ if (!nativeData)
+ return;
+
+ env->GetByteArrayRegion(data, 0, length, nativeData);
+ payload = QByteArray(reinterpret_cast<const char*>(nativeData),
+ length); //takes deep copy of data
+ free(nativeData);
+ }
QMetaObject::invokeMethod(hub, "characteristicRead", Qt::QueuedConnection,
Q_ARG(QBluetoothUuid, serviceUuid),
Q_ARG(int, handle),
Q_ARG(QBluetoothUuid, charUuid),
Q_ARG(int, properties),
- Q_ARG(QByteArray, qtArray));
- free(nativeData);
+ Q_ARG(QByteArray, payload));
+
+}
+
+void LowEnergyNotificationHub::lowEnergy_descriptorRead(
+ JNIEnv *env, jobject, jlong qtObject, jobject sUuid, jobject cUuid,
+ jint handle, jobject dUuid, jbyteArray data)
+{
+ lock.lockForRead();
+ LowEnergyNotificationHub *hub = hubMap()->value(qtObject);
+ lock.unlock();
+ if (!hub)
+ return;
+
+ const QBluetoothUuid serviceUuid(QAndroidJniObject(sUuid).toString());
+ if (serviceUuid.isNull())
+ return;
+
+ const QBluetoothUuid charUuid(QAndroidJniObject(cUuid).toString());
+ const QBluetoothUuid descUuid(QAndroidJniObject(dUuid).toString());
+ if (charUuid.isNull() || descUuid.isNull())
+ return;
+
+ QByteArray payload;
+ if (data) { //empty Java byte array is 0x0
+ jsize length = env->GetArrayLength(data);
+ jbyte* nativeData = (jbyte*) malloc(length * sizeof(jbyte));
+ if (!nativeData)
+ return;
+
+ env->GetByteArrayRegion(data, 0, length, nativeData);
+ payload = QByteArray(reinterpret_cast<const char*>(nativeData),
+ length); //takes deep copy of data
+ free(nativeData);
+ }
+
+ QMetaObject::invokeMethod(hub, "descriptorRead", Qt::QueuedConnection,
+ Q_ARG(QBluetoothUuid, serviceUuid),
+ Q_ARG(QBluetoothUuid, charUuid),
+ Q_ARG(int, handle),
+ Q_ARG(QBluetoothUuid, descUuid),
+ Q_ARG(QByteArray, payload));
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/android/lowenergynotificationhub_p.h b/src/bluetooth/android/lowenergynotificationhub_p.h
index 7a1e2d79..39008a65 100644
--- a/src/bluetooth/android/lowenergynotificationhub_p.h
+++ b/src/bluetooth/android/lowenergynotificationhub_p.h
@@ -59,11 +59,15 @@ public:
static void lowEnergy_servicesDiscovered(JNIEnv*, jobject, jlong qtObject,
jint errorCode, jobject uuidList);
static void lowEnergy_serviceDetailsDiscovered(JNIEnv *, jobject,
- jlong qtObject, jobject uuid);
+ jlong qtObject, jobject uuid,
+ jint startHandle, jint endHandle);
static void lowEnergy_characteristicRead(JNIEnv*env, jobject, jlong qtObject,
jobject serviceUuid,
jint handle, jobject charUuid,
jint properties, jbyteArray data);
+ static void lowEnergy_descriptorRead(JNIEnv *env, jobject, jlong qtObject,
+ jobject sUuid, jobject cUuid,
+ jint handle, jobject dUuid, jbyteArray data);
QAndroidJniObject javaObject()
{
@@ -74,10 +78,13 @@ signals:
void connectionUpdated(QLowEnergyController::ControllerState newState,
QLowEnergyController::Error errorCode);
void servicesDiscovered(QLowEnergyController::Error errorCode, const QString &uuids);
- void serviceDetailsDiscoveryFinished(const QString& serviceUuid);
+ void serviceDetailsDiscoveryFinished(const QString& serviceUuid,
+ int startHandle, int endHandle);
void characteristicRead(const QBluetoothUuid &serviceUuid,
int handle, const QBluetoothUuid &charUuid,
- int properties, const QByteArray& data);
+ int properties, const QByteArray &data);
+ void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
+ int handle, const QBluetoothUuid &descUuid, const QByteArray &data);
public slots:
private:
diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp
index c3cdde83..f832d868 100644
--- a/src/bluetooth/qlowenergycontroller_android.cpp
+++ b/src/bluetooth/qlowenergycontroller_android.cpp
@@ -72,7 +72,8 @@ void QLowEnergyControllerPrivate::connectToDevice()
this, &QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished);
connect(hub, &LowEnergyNotificationHub::characteristicRead,
this, &QLowEnergyControllerPrivate::characteristicRead);
-
+ connect(hub, &LowEnergyNotificationHub::descriptorRead,
+ this, &QLowEnergyControllerPrivate::descriptorRead);
}
if (!hub->javaObject().isValid()) {
@@ -129,7 +130,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s
bool result = hub->javaObject().callMethod<jboolean>("discoverServiceDetails",
"(Ljava/lang/String;)Z",
uuid.object<jstring>());
- if (!result || true) {
+ if (!result) {
QSharedPointer<QLowEnergyServicePrivate> servicePrivate =
serviceList.value(service);
if (!servicePrivate.isNull()) {
@@ -219,7 +220,7 @@ void QLowEnergyControllerPrivate::servicesDiscovered(
}
void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished(
- const QString &serviceUuid)
+ const QString &serviceUuid, int startHandle, int endHandle)
{
const QBluetoothUuid service(serviceUuid);
if (!serviceList.contains(service)) {
@@ -228,13 +229,20 @@ void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished(
return;
}
+ //update service data
QSharedPointer<QLowEnergyServicePrivate> pointer =
serviceList.value(service);
+ pointer->startHandle = startHandle;
+ pointer->endHandle = endHandle;
+
+ qCDebug(QT_BT_ANDROID) << "Service" << serviceUuid << "discovered (start:"
+ << startHandle << "end:" << endHandle << ")";
+
pointer->setState(QLowEnergyService::ServiceDiscovered);
}
void QLowEnergyControllerPrivate::characteristicRead(
- const QBluetoothUuid& serviceUuid, int handle,
+ const QBluetoothUuid &serviceUuid, int handle,
const QBluetoothUuid &charUuid, int properties, const QByteArray &data)
{
if (!serviceList.contains(serviceUuid))
@@ -247,14 +255,44 @@ void QLowEnergyControllerPrivate::characteristicRead(
QLowEnergyServicePrivate::CharData &charDetails =
service->characteristicList[charHandle];
- //Android uses same properties value as Qt which is the Bluetooth LE standard
+ //Android uses same property value as Qt which is the Bluetooth LE standard
charDetails.properties = QLowEnergyCharacteristic::PropertyType(properties);
charDetails.uuid = charUuid;
charDetails.value = data;
//value handle always one larger than characteristics value handle
charDetails.valueHandle = charHandle + 1;
+}
- //service->characteristicList[charHandle] = charDetails;
+void QLowEnergyControllerPrivate::descriptorRead(
+ const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
+ int descHandle, const QBluetoothUuid &descUuid, const QByteArray &data)
+{
+ if (!serviceList.contains(serviceUuid))
+ return;
+
+ QSharedPointer<QLowEnergyServicePrivate> service =
+ serviceList.value(serviceUuid);
+
+ bool entryUpdated = false;
+ foreach (QLowEnergyHandle charHandle, service->characteristicList.keys()) {
+ QLowEnergyServicePrivate::CharData &charDetails =
+ service->characteristicList[charHandle];
+ if (charDetails.uuid != charUuid)
+ continue;
+
+ // new entry created if it doesn't exist
+ QLowEnergyServicePrivate::DescData &descDetails =
+ charDetails.descriptorList[descHandle];
+ descDetails.uuid = descUuid;
+ descDetails.value = data;
+ entryUpdated = true;
+ break;
+ }
+
+ if (!entryUpdated) {
+ qCWarning(QT_BT_ANDROID) << "Cannot find/update descriptor"
+ << descUuid << charUuid << serviceUuid;
+ }
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index 6f416b11..6a72fa6c 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -179,10 +179,13 @@ private slots:
QLowEnergyController::Error errorCode);
void servicesDiscovered(QLowEnergyController::Error errorCode,
const QString &foundServices);
- void serviceDetailsDiscoveryFinished(const QString& serviceUuid);
+ void serviceDetailsDiscoveryFinished(const QString& serviceUuid,
+ int startHandle, int endHandle);
void characteristicRead(const QBluetoothUuid &serviceUuid, int handle,
const QBluetoothUuid &charUuid, int properties,
const QByteArray& data);
+ void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
+ int handle, const QBluetoothUuid &descUuid, const QByteArray &data);
#endif
private: