summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-07-22 11:59:27 +0200
committerAlex Blasche <alexander.blasche@digia.com>2014-07-23 15:28:49 +0200
commit199bd8306541c3987cc4aae7d7f93af31717d3b5 (patch)
tree004d9a1a034d0abc39145b79d9c4b9edda4e6502
parent58d1b5bdffc25f4ff22dcd00f0572c9c4fac3f88 (diff)
Detect secondary services and display service type in lowenergyscanner
QLowEnergyService::ServiceState was converted to a flag because a primary and secondary service can be included by other services. Change-Id: I425ce8e3f39ee07cccee2763b57a049a624f6178 Reviewed-by: Fabian Bumberger <fbumberger@rim.com>
-rw-r--r--examples/bluetooth/lowenergyscanner/assets/Services.qml6
-rw-r--r--examples/bluetooth/lowenergyscanner/serviceinfo.cpp19
-rw-r--r--examples/bluetooth/lowenergyscanner/serviceinfo.h2
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp31
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h3
-rw-r--r--src/bluetooth/qlowenergyservice.cpp14
-rw-r--r--src/bluetooth/qlowenergyservice.h7
-rw-r--r--src/bluetooth/qlowenergyserviceprivate_p.h2
8 files changed, 69 insertions, 15 deletions
diff --git a/examples/bluetooth/lowenergyscanner/assets/Services.qml b/examples/bluetooth/lowenergyscanner/assets/Services.qml
index 361f14c1..e4e802d2 100644
--- a/examples/bluetooth/lowenergyscanner/assets/Services.qml
+++ b/examples/bluetooth/lowenergyscanner/assets/Services.qml
@@ -108,6 +108,12 @@ Rectangle {
}
Label {
+ textContent: modelData.serviceType
+ font.pointSize: serviceName.font.pointSize * 0.5
+ anchors.top: serviceName.bottom
+ }
+
+ Label {
id: serviceUuid
font.pointSize: serviceName.font.pointSize * 0.5
textContent: modelData.serviceUuid
diff --git a/examples/bluetooth/lowenergyscanner/serviceinfo.cpp b/examples/bluetooth/lowenergyscanner/serviceinfo.cpp
index 19b99b9f..c05422ca 100644
--- a/examples/bluetooth/lowenergyscanner/serviceinfo.cpp
+++ b/examples/bluetooth/lowenergyscanner/serviceinfo.cpp
@@ -64,6 +64,25 @@ QString ServiceInfo::getName() const
return m_service->serviceName();
}
+QString ServiceInfo::getType() const
+{
+ if (!m_service)
+ return QString();
+
+ QString result;
+ if (m_service->type() & QLowEnergyService::PrimaryService)
+ result += QStringLiteral("primary");
+ else
+ result += QStringLiteral("secondary");
+
+ if (m_service->type() & QLowEnergyService::IncludedService)
+ result += QStringLiteral(" included");
+
+ result.prepend('<').append('>');
+
+ return result;
+}
+
QString ServiceInfo::getUuid() const
{
if (!m_service)
diff --git a/examples/bluetooth/lowenergyscanner/serviceinfo.h b/examples/bluetooth/lowenergyscanner/serviceinfo.h
index d02c79ba..1d35b1b7 100644
--- a/examples/bluetooth/lowenergyscanner/serviceinfo.h
+++ b/examples/bluetooth/lowenergyscanner/serviceinfo.h
@@ -48,12 +48,14 @@ class ServiceInfo: public QObject
Q_OBJECT
Q_PROPERTY(QString serviceName READ getName NOTIFY serviceChanged)
Q_PROPERTY(QString serviceUuid READ getUuid NOTIFY serviceChanged)
+ Q_PROPERTY(QString serviceType READ getType NOTIFY serviceChanged)
public:
ServiceInfo();
ServiceInfo(QLowEnergyService *service);
QLowEnergyService *service() const;
QString getUuid() const;
QString getName() const;
+ QString getType() const;
Q_SIGNALS:
void serviceChanged();
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index d3c7e024..795bdfb8 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -56,6 +56,7 @@
#define ATT_MAX_LE_MTU 0x200
#define GATT_PRIMARY_SERVICE 0x2800
+#define GATT_SECONDARY_SERVICE 0x2801
#define GATT_CHARACTERISTIC 0x2803
// GATT commands
@@ -396,8 +397,13 @@ void QLowEnergyControllerPrivate::processReply(
// Discovering services
Q_ASSERT(request.command == ATT_OP_READ_BY_GROUP_REQUEST);
+ const quint16 type = request.reference.toUInt();
+
if (isErrorResponse) {
- q->discoveryFinished();
+ if (type == GATT_SECONDARY_SERVICE)
+ q->discoveryFinished();
+ else // search for secondary services
+ sendReadByGroupRequest(0x0001, 0xFFFF, GATT_SECONDARY_SERVICE);
break;
}
@@ -427,6 +433,8 @@ void QLowEnergyControllerPrivate::processReply(
priv->uuid = uuid;
priv->startHandle = start;
priv->endHandle = end;
+ if (type != GATT_PRIMARY_SERVICE) //unset PrimaryService bit
+ priv->type &= ~QLowEnergyService::PrimaryService;
priv->setController(this);
QSharedPointer<QLowEnergyServicePrivate> pointer(priv);
@@ -435,10 +443,14 @@ void QLowEnergyControllerPrivate::processReply(
emit q->serviceDiscovered(uuid);
}
- if (end != 0xFFFF)
- sendReadByGroupRequest(end+1, 0xFFFF);
- else
- emit q->discoveryFinished();
+ if (end != 0xFFFF) {
+ sendReadByGroupRequest(end+1, 0xFFFF, type);
+ } else {
+ if (type == GATT_SECONDARY_SERVICE)
+ emit q->discoveryFinished();
+ else // search for secondary services
+ sendReadByGroupRequest(0x0001, 0xFFFF, GATT_SECONDARY_SERVICE);
+ }
}
break;
case ATT_OP_READ_BY_TYPE_REQUEST: //in case of error
@@ -689,19 +701,19 @@ void QLowEnergyControllerPrivate::processReply(
void QLowEnergyControllerPrivate::discoverServices()
{
- sendReadByGroupRequest(0x0001, 0xFFFF);
+ sendReadByGroupRequest(0x0001, 0xFFFF, GATT_PRIMARY_SERVICE);
}
void QLowEnergyControllerPrivate::sendReadByGroupRequest(
- QLowEnergyHandle start, QLowEnergyHandle end)
+ QLowEnergyHandle start, QLowEnergyHandle end, quint16 type)
{
- //call for primary services
+ //call for primary and secondary services
quint8 packet[GRP_TYPE_REQ_SIZE];
packet[0] = ATT_OP_READ_BY_GROUP_REQUEST;
bt_put_unaligned(htobs(start), (quint16 *) &packet[1]);
bt_put_unaligned(htobs(end), (quint16 *) &packet[3]);
- bt_put_unaligned(htobs(GATT_PRIMARY_SERVICE), (quint16 *) &packet[5]);
+ bt_put_unaligned(htobs(type), (quint16 *) &packet[5]);
QByteArray data(GRP_TYPE_REQ_SIZE, Qt::Uninitialized);
memcpy(data.data(), packet, GRP_TYPE_REQ_SIZE);
@@ -711,6 +723,7 @@ void QLowEnergyControllerPrivate::sendReadByGroupRequest(
Request request;
request.payload = data;
request.command = ATT_OP_READ_BY_GROUP_REQUEST;
+ request.reference = type;
openRequests.enqueue(request);
sendNextPendingRequest();
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index e00e7a87..38178028 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -132,7 +132,8 @@ private:
void sendNextPendingRequest();
void processReply(const Request &request, const QByteArray &reply);
- void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end);
+ void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end,
+ quint16 type);
void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData,
QLowEnergyHandle nextHandle);
void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor);
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 11485183..0bc9dc55 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -51,6 +51,18 @@
QT_BEGIN_NAMESPACE
/*!
+ \enum QBluetoothDeviceInfo::ServiceType
+
+ This enum describes the type of the service.
+
+ \value PrimaryService The service is a top-level/primary service.
+ If this type flag is not set the service is considered
+ to be a secondary service. Each service may be included
+ by another service which is indicated by \l IncludedService.
+ \value IncludedService The service is included by another service.
+*/
+
+/*!
\internal
QLowEnergyControllerPrivate creates instances of this class.
@@ -92,7 +104,7 @@ QLowEnergyService::ServiceState QLowEnergyService::state() const
return d_ptr->state;
}
-QLowEnergyService::ServiceType QLowEnergyService::type() const
+QLowEnergyService::ServiceTypes QLowEnergyService::type() const
{
return d_ptr->type;
}
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index 9fe56280..541d6c61 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -54,9 +54,10 @@ class Q_BLUETOOTH_EXPORT QLowEnergyService : public QObject
Q_OBJECT
public:
enum ServiceType {
- PrimaryService = 0,
- IncludedService
+ PrimaryService = 0x0001,
+ IncludedService = 0x0002
};
+ Q_DECLARE_FLAGS(ServiceTypes, ServiceType)
enum ServiceError {
NoError = 0,
@@ -76,7 +77,7 @@ public:
~QLowEnergyService();
QList<QSharedPointer<QLowEnergyService> > includedServices() const;
- QLowEnergyService::ServiceType type() const;
+ QLowEnergyService::ServiceTypes type() const;
QLowEnergyService::ServiceState state() const;
QLowEnergyCharacteristic characteristic(const QBluetoothUuid &uuid) const;
diff --git a/src/bluetooth/qlowenergyserviceprivate_p.h b/src/bluetooth/qlowenergyserviceprivate_p.h
index 25b18e2d..ab19aa95 100644
--- a/src/bluetooth/qlowenergyserviceprivate_p.h
+++ b/src/bluetooth/qlowenergyserviceprivate_p.h
@@ -96,7 +96,7 @@ public:
QLowEnergyHandle endHandle;
QBluetoothUuid uuid;
- QLowEnergyService::ServiceType type;
+ QLowEnergyService::ServiceTypes type;
QLowEnergyService::ServiceState state;
QLowEnergyService::ServiceError lastError;