summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-06-23 08:16:28 +0200
committerAlex Blasche <alexander.blasche@digia.com>2014-06-26 16:36:15 +0200
commit3c9c77c94d747a568a22421c0b0ada086463dbad (patch)
treef948d74a67e7aada343f7a4af4fefca18fcff4db /src
parent417ac65051bba0f91185f437c90a3d6f36b99d60 (diff)
Read characteristic values on Bluez
Change-Id: I6427c6dad133ca11852f5295cf37720addec7644 Reviewed-by: Fabian Bumberger <fbumberger@rim.com>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/qlowenergycharacteristic.cpp13
-rw-r--r--src/bluetooth/qlowenergycharacteristic.h2
-rw-r--r--src/bluetooth/qlowenergycontrollernew.cpp18
-rw-r--r--src/bluetooth/qlowenergycontrollernew_bluez.cpp109
-rw-r--r--src/bluetooth/qlowenergycontrollernew_p.h11
-rw-r--r--src/bluetooth/qlowenergyservice.cpp14
-rw-r--r--src/bluetooth/qlowenergyservice.h7
7 files changed, 134 insertions, 40 deletions
diff --git a/src/bluetooth/qlowenergycharacteristic.cpp b/src/bluetooth/qlowenergycharacteristic.cpp
index 0d0ad60c..10136c10 100644
--- a/src/bluetooth/qlowenergycharacteristic.cpp
+++ b/src/bluetooth/qlowenergycharacteristic.cpp
@@ -100,17 +100,10 @@ QLowEnergyCharacteristic::QLowEnergyCharacteristic():
upon write.
*/
QLowEnergyCharacteristic::QLowEnergyCharacteristic(const QLowEnergyCharacteristic &other):
- d_ptr(other.d_ptr)
+ d_ptr(other.d_ptr), data(0)
{
- if (!other.data) {
- if (data) {
- delete data;
- data = 0;
- }
- } else {
- if (!data)
- data = new QLowEnergyCharacteristicPrivate();
-
+ if (other.data) {
+ data = new QLowEnergyCharacteristicPrivate();
data->handle = other.data->handle;
}
}
diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h
index 7dc91f43..6454ef67 100644
--- a/src/bluetooth/qlowenergycharacteristic.h
+++ b/src/bluetooth/qlowenergycharacteristic.h
@@ -92,6 +92,8 @@ public:
protected:
QSharedPointer<QLowEnergyServicePrivate> d_ptr;
+
+ friend class QLowEnergyService;
QLowEnergyCharacteristicPrivate *data;
QLowEnergyCharacteristic(QSharedPointer<QLowEnergyServicePrivate> p,
QLowEnergyHandle handle);
diff --git a/src/bluetooth/qlowenergycontrollernew.cpp b/src/bluetooth/qlowenergycontrollernew.cpp
index 8b98c6b9..75fcce86 100644
--- a/src/bluetooth/qlowenergycontrollernew.cpp
+++ b/src/bluetooth/qlowenergycontrollernew.cpp
@@ -108,6 +108,24 @@ void QLowEnergyControllerNewPrivate::invalidateServices()
serviceList.clear();
}
+QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerNewPrivate::serviceForHandle(
+ QLowEnergyHandle handle)
+{
+ foreach (QSharedPointer<QLowEnergyServicePrivate> service, serviceList.values())
+ if (service->startHandle <= handle && handle <= service->endHandle)
+ return service;
+
+ return QSharedPointer<QLowEnergyServicePrivate>();
+}
+
+void QLowEnergyControllerNewPrivate::updateValueOfCharacteristic(
+ QLowEnergyHandle charHandle, const QByteArray &value)
+{
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
+ if (!service.isNull() && service->characteristicList.contains(charHandle))
+ service->characteristicList[charHandle].value = value;
+}
+
QLowEnergyControllerNew::QLowEnergyControllerNew(
const QBluetoothAddress &remoteDevice,
QObject *parent)
diff --git a/src/bluetooth/qlowenergycontrollernew_bluez.cpp b/src/bluetooth/qlowenergycontrollernew_bluez.cpp
index 8249f1fc..1b5ea1db 100644
--- a/src/bluetooth/qlowenergycontrollernew_bluez.cpp
+++ b/src/bluetooth/qlowenergycontrollernew_bluez.cpp
@@ -56,9 +56,11 @@
// GATT commands
#define ATT_OP_ERROR_RESPONSE 0x1
-#define ATT_OP_READ_BY_TYPE_REQUEST 0x8
+#define ATT_OP_READ_BY_TYPE_REQUEST 0x8 //discover characteristics
#define ATT_OP_READ_BY_TYPE_RESPONSE 0x9
-#define ATT_OP_READ_BY_GROUP_REQUEST 0x10
+#define ATT_OP_READ_REQUEST 0xA //read characteristic value
+#define ATT_OP_READ_RESPONSE 0xB
+#define ATT_OP_READ_BY_GROUP_REQUEST 0x10 //discover services
#define ATT_OP_READ_BY_GROUP_RESPONSE 0x11
// GATT error codes
@@ -80,9 +82,6 @@
#define ATT_ERROR_APPLICATION 0x10
#define ATT_ERROR_INSUF_RESOURCES 0x11
-
-
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
@@ -231,7 +230,7 @@ void QLowEnergyControllerNewPrivate::l2cpReadyRead()
{
requestPending = false;
const QByteArray reply = l2cpSocket->readAll();
- //qDebug() << response.size() << "data:" << response.toHex();
+ qDebug() << reply.size() << "data:" << reply.toHex();
if (reply.isEmpty())
return;
@@ -248,8 +247,8 @@ void QLowEnergyControllerNewPrivate::sendNextPendingRequest()
return;
const Request &request = openRequests.head();
- qCDebug(QT_BT_BLUEZ) << "Sending request, type:" << hex << request.command
- << request.payload.toHex();
+// qCDebug(QT_BT_BLUEZ) << "Sending request, type:" << hex << request.command
+// << request.payload.toHex();
requestPending = true;
qint64 result = l2cpSocket->write(request.payload.constData(),
@@ -285,7 +284,7 @@ void QLowEnergyControllerNewPrivate::processReply(
if (isErrorResponse) {
q->discoveryFinished();
- return;
+ break;
}
QLowEnergyHandle start = 0, end = 0;
@@ -308,8 +307,8 @@ void QLowEnergyControllerNewPrivate::processReply(
offset += elementLength;
- //qDebug() << "Found uuid:" << uuid << "start handle:" << hex
- // << start << "end handle:" << end;
+// qDebug() << "Found uuid:" << uuid << "start handle:" << hex
+// << start << "end handle:" << end;
QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
priv->uuid = uuid;
@@ -327,7 +326,6 @@ void QLowEnergyControllerNewPrivate::processReply(
sendReadByGroupRequest(end+1, 0xFFFF);
else
emit q->discoveryFinished();
-
}
break;
case ATT_OP_READ_BY_TYPE_REQUEST: //in case of error
@@ -341,8 +339,8 @@ void QLowEnergyControllerNewPrivate::processReply(
if (isErrorResponse) {
//we reached end of service handle
//just finish up characteristic discovery
- p->setState(QLowEnergyService::ServiceDiscovered);
- return;
+ readServiceCharacteristicValues(p->uuid);
+ break;
}
/* packet format:
@@ -378,23 +376,42 @@ void QLowEnergyControllerNewPrivate::processReply(
p->characteristicList[startHandle] = characteristic;
- qDebug() << "Found handle:" << hex << startHandle
- << "properties:" << flags
- << "value handle:" << valueHandle
- << "uuid:" << uuid.toString();
+// qDebug() << "Found handle:" << hex << startHandle
+// << "properties:" << flags
+// << "value handle:" << valueHandle
+// << "uuid:" << uuid.toString();
}
if (startHandle + 1 < p->endHandle) // more chars to discover
sendReadByTypeRequest(p, startHandle + 1);
else
- p->setState(QLowEnergyService::ServiceDiscovered);
+ readServiceCharacteristicValues(p->uuid);
+ }
+ break;
+ case ATT_OP_READ_REQUEST: //error case
+ case ATT_OP_READ_RESPONSE:
+ {
+ Q_ASSERT(request.command == ATT_OP_READ_REQUEST);
+
+ if (isErrorResponse) {
+ // we ignore any error and go over to next message
+ break;
+ }
+
+ QLowEnergyHandle charHandle = (QLowEnergyHandle) request.reference.toUInt();
+ QByteArray a = response.mid(1);
+ updateValueOfCharacteristic(charHandle, response.mid(1).toHex());
+ if (request.reference2.toBool()) {
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
+ Q_ASSERT(!service.isNull());
+ service->setState(QLowEnergyService::ServiceDiscovered);
+ }
}
break;
default:
qCDebug(QT_BT_BLUEZ) << "Unknown packet: " << response.toHex();
+ break;
}
-
-
}
void QLowEnergyControllerNewPrivate::discoverServices()
@@ -419,6 +436,8 @@ void QLowEnergyControllerNewPrivate::sendReadByGroupRequest(
QByteArray data(GRP_TYPE_REQ_SIZE, Qt::Uninitialized);
memcpy(data.data(), packet, GRP_TYPE_REQ_SIZE);
+// qDebug() << "Sending read_by_group_type request, startHandle:" << hex
+// << start << "endHandle:" << end;
Request request;
request.payload = data;
@@ -458,9 +477,9 @@ void QLowEnergyControllerNewPrivate::sendReadByTypeRequest(
QByteArray data(READ_BY_TYPE_REQ_SIZE, Qt::Uninitialized);
memcpy(data.data(), packet, READ_BY_TYPE_REQ_SIZE);
- qDebug() << "Sending read_by_type request, startHandle:" << hex
- << nextHandle << "endHandle:" << serviceData->endHandle
- << "packet:" << data.toHex();
+// qDebug() << "Sending read_by_type request, startHandle:" << hex
+// << nextHandle << "endHandle:" << serviceData->endHandle
+// << "packet:" << data.toHex();
Request request;
request.payload = data;
@@ -471,5 +490,47 @@ void QLowEnergyControllerNewPrivate::sendReadByTypeRequest(
sendNextPendingRequest();
}
+void QLowEnergyControllerNewPrivate::readServiceCharacteristicValues(
+ const QBluetoothUuid &serviceUuid)
+{
+#define READ_REQUEST_SIZE 3
+ quint8 packet[READ_REQUEST_SIZE];
+ qCDebug(QT_BT_BLUEZ) << "Reading characteristic values for"
+ << serviceUuid.toString();
+
+ bool oneReadRequested = false;
+ QSharedPointer<QLowEnergyServicePrivate> service = serviceList.value(serviceUuid);
+ const QList<QLowEnergyHandle> &keys = service->characteristicList.keys();
+ for (int i = 0; i < keys.count(); i++) {
+ QLowEnergyHandle charHandle = keys[i];
+ const QLowEnergyServicePrivate::CharData &charDetails =
+ service->characteristicList[charHandle];
+
+ //Don't try to read readOnly property
+ if (!(charDetails.properties & QLowEnergyCharacteristic::Read))
+ continue;
+
+ packet[0] = ATT_OP_READ_REQUEST;
+ bt_put_unaligned(htobs(charDetails.valueHandle), (quint16 *) &packet[1]);
+
+ QByteArray data(READ_REQUEST_SIZE, Qt::Uninitialized);
+ memcpy(data.data(), packet, READ_REQUEST_SIZE);
+
+ Request request;
+ request.payload = data;
+ request.command = ATT_OP_READ_REQUEST;
+ request.reference = charHandle;
+ //last entry?
+ request.reference2 = QVariant((bool)(i + 1 == keys.count()));
+ openRequests.enqueue(request);
+ oneReadRequested = true;
+ }
+
+ if (!oneReadRequested)
+ service->setState(QLowEnergyService::ServiceDiscovered);
+
+ sendNextPendingRequest();
+}
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontrollernew_p.h b/src/bluetooth/qlowenergycontrollernew_p.h
index 3f1862dc..f6bc06e5 100644
--- a/src/bluetooth/qlowenergycontrollernew_p.h
+++ b/src/bluetooth/qlowenergycontrollernew_p.h
@@ -83,6 +83,13 @@ public:
void discoverServiceDetails(const QBluetoothUuid &service);
+ // misc lookup helpers
+ QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(
+ QLowEnergyHandle handle);
+ void updateValueOfCharacteristic(QLowEnergyHandle charHandle,
+ const QByteArray &value);
+
+
QBluetoothAddress remoteDevice;
QBluetoothAddress localAdapter;
@@ -100,7 +107,10 @@ private:
struct Request {
quint8 command;
QByteArray payload;
+ // TODO reference below is ugly but until we know all commands and their
+ // requirements this is WIP
QVariant reference;
+ QVariant reference2;
};
QQueue<Request> openRequests;
bool requestPending;
@@ -111,6 +121,7 @@ private:
void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end);
void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData,
QLowEnergyHandle nextHandle);
+ void readServiceCharacteristicValues(const QBluetoothUuid &service);
private slots:
void l2cpConnected();
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 0080dee9..d8f80397 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -44,6 +44,8 @@
#include <QtBluetooth/QLowEnergyService>
#include <QtBluetooth/QLowEnergyCharacteristicInfo>
+#include <algorithm>
+
#include "qlowenergycontrollernew_p.h"
#include "qlowenergyserviceprivate_p.h"
@@ -94,10 +96,16 @@ QLowEnergyService::ServiceType QLowEnergyService::type() const
}
-QList<QLowEnergyCharacteristicInfo> QLowEnergyService::characteristics() const
+QList<QLowEnergyCharacteristic> QLowEnergyService::characteristics() const
{
- //TODO implement
- QList<QLowEnergyCharacteristicInfo> results;
+ QList<QLowEnergyCharacteristic> results;
+ QList<QLowEnergyHandle> handles = d_ptr->characteristicList.keys();
+ std::sort(handles.begin(), handles.end());
+
+ foreach (const QLowEnergyHandle &handle, handles) {
+ QLowEnergyCharacteristic characteristic(d_ptr, handle);
+ results.append(characteristic);
+ }
return results;
}
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index af4b657d..c2ecc6b0 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -42,7 +42,8 @@
#define QLOWENERGYSERVICE_H
#include <QtBluetooth/QBluetoothAddress>
-#include <QtBluetooth/QLowEnergyCharacteristicInfo>
+#include <QtBluetooth/QBluetoothUuid>
+#include <QtBluetooth/QLowEnergyCharacteristic>
QT_BEGIN_NAMESPACE
@@ -76,7 +77,7 @@ public:
QLowEnergyService::ServiceState state() const;
- QList<QLowEnergyCharacteristicInfo> characteristics() const;
+ QList<QLowEnergyCharacteristic> characteristics() const;
QBluetoothUuid serviceUuid() const;
QString serviceName() const;
@@ -87,7 +88,7 @@ public:
Q_SIGNALS:
void stateChanged(QLowEnergyService::ServiceState newState);
- void characteristicChanged(const QLowEnergyCharacteristicInfo &info,
+ void characteristicChanged(const QLowEnergyCharacteristic &info,
const QByteArray &value);
void descriptorChanged(const QLowEnergyDescriptorInfo &info,
const QByteArray &value);