summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp37
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp68
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h3
3 files changed, 95 insertions, 13 deletions
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 2337268d..053ca980 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -931,13 +931,24 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
return nullptr;
}
+ Q_D(QLowEnergyController);
+ QLowEnergyService *newService = d->addServiceHelper(service);
+ if (newService)
+ newService->setParent(parent);
+
+ return newService;
+}
+
+QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper(
+ const QLowEnergyServiceData &service)
+{
// Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit).
// Since this is not mandatory, we ignore it here and let the caller take responsibility
// for it.
const auto servicePrivate = QSharedPointer<QLowEnergyServicePrivate>::create();
servicePrivate->state = QLowEnergyService::LocalService;
- servicePrivate->setController(d_ptr);
+ servicePrivate->setController(this);
servicePrivate->uuid = service.uuid();
servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary
? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService;
@@ -947,13 +958,13 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
}
// Spec v4.2, Vol 3, Part G, Section 3.
- const QLowEnergyHandle oldLastHandle = d_ptr->lastLocalHandle;
- servicePrivate->startHandle = ++d_ptr->lastLocalHandle; // Service declaration.
- d_ptr->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations.
+ const QLowEnergyHandle oldLastHandle = this->lastLocalHandle;
+ servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration.
+ this->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations.
foreach (const QLowEnergyCharacteristicData &cd, service.characteristics()) {
- const QLowEnergyHandle declHandle = ++d_ptr->lastLocalHandle;
+ const QLowEnergyHandle declHandle = ++this->lastLocalHandle;
QLowEnergyServicePrivate::CharData charData;
- charData.valueHandle = ++d_ptr->lastLocalHandle;
+ charData.valueHandle = ++this->lastLocalHandle;
charData.uuid = cd.uuid();
charData.properties = cd.properties();
charData.value = cd.value();
@@ -961,21 +972,21 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData
QLowEnergyServicePrivate::DescData descData;
descData.uuid = dd.uuid();
descData.value = dd.value();
- charData.descriptorList.insert(++d_ptr->lastLocalHandle, descData);
+ charData.descriptorList.insert(++this->lastLocalHandle, descData);
}
servicePrivate->characteristicList.insert(declHandle, charData);
}
- servicePrivate->endHandle = d_ptr->lastLocalHandle;
- const bool handleOverflow = d_ptr->lastLocalHandle <= oldLastHandle;
+ servicePrivate->endHandle = this->lastLocalHandle;
+ const bool handleOverflow = this->lastLocalHandle <= oldLastHandle;
if (handleOverflow) {
qCWarning(QT_BT) << "Not enough attribute handles left to create this service";
- d_ptr->lastLocalHandle = oldLastHandle;
+ this->lastLocalHandle = oldLastHandle;
return nullptr;
}
- d_ptr->localServices.insert(servicePrivate->uuid, servicePrivate);
- d_ptr->addToGenericAttributeList(service, servicePrivate->startHandle);
- return new QLowEnergyService(servicePrivate, parent);
+ this->localServices.insert(servicePrivate->uuid, servicePrivate);
+ this->addToGenericAttributeList(service, servicePrivate->startHandle);
+ return new QLowEnergyService(servicePrivate);
}
/*!
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index 583c0e27..0744bcc4 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -530,6 +530,8 @@ void QLowEnergyControllerPrivate::connectToDevice()
if (l2cpSocket)
delete l2cpSocket;
+ createServicesForCentralIfRequired();
+
// check for active running connections
// BlueZ 5.37+ (maybe even earlier versions) can have pending BTLE connections
// Only one active L2CP socket to CID 0x4 possible at a time
@@ -644,6 +646,72 @@ void QLowEnergyControllerPrivate::establishL2cpClientSocket()
loadSigningDataIfNecessary(LocalSigningKey);
}
+void QLowEnergyControllerPrivate::createServicesForCentralIfRequired()
+{
+ //only enable when requested
+ //for now we use env variable to activate the feature
+ if (Q_LIKELY(!qEnvironmentVariableIsSet("QT_DEFAULT_CENTRAL_SERVICES")))
+ return; //nothing to do
+
+ //do not add the services each time we start a connection
+ if (localServices.contains(QBluetoothUuid(QBluetoothUuid::GenericAccess)))
+ return;
+
+ qCDebug(QT_BT_BLUEZ) << "Creating default GAP/GATT services";
+
+ //populate Generic Access service
+ //for now the values are static
+ QLowEnergyServiceData gapServiceData;
+ gapServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+ gapServiceData.setUuid(QBluetoothUuid::GenericAccess);
+
+ QLowEnergyCharacteristicData gapDeviceName;
+ gapDeviceName.setUuid(QBluetoothUuid::DeviceName);
+ gapDeviceName.setProperties(QLowEnergyCharacteristic::Read);
+
+ QBluetoothLocalDevice mainAdapter;
+ gapDeviceName.setValue(mainAdapter.name().toLatin1()); //static name
+
+ QLowEnergyCharacteristicData gapAppearance;
+ gapAppearance.setUuid(QBluetoothUuid::Appearance);
+ gapAppearance.setProperties(QLowEnergyCharacteristic::Read);
+ gapAppearance.setValue(QByteArray::fromHex("80")); // Generic Computer (0x80)
+
+ QLowEnergyCharacteristicData gapPrivacyFlag;
+ gapPrivacyFlag.setUuid(QBluetoothUuid::PeripheralPrivacyFlag);
+ gapPrivacyFlag.setProperties(QLowEnergyCharacteristic::Read);
+ gapPrivacyFlag.setValue(QByteArray::fromHex("00")); // disable privacy
+
+ gapServiceData.addCharacteristic(gapDeviceName);
+ gapServiceData.addCharacteristic(gapAppearance);
+ gapServiceData.addCharacteristic(gapPrivacyFlag);
+
+ Q_Q(QLowEnergyController);
+ QLowEnergyService *service = addServiceHelper(gapServiceData);
+ if (service)
+ service->setParent(q);
+
+ QLowEnergyServiceData gattServiceData;
+ gattServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
+ gattServiceData.setUuid(QBluetoothUuid::GenericAttribute);
+
+ QLowEnergyCharacteristicData serviceChangedChar;
+ serviceChangedChar.setUuid(QBluetoothUuid::ServiceChanged);
+ serviceChangedChar.setProperties(QLowEnergyCharacteristic::Indicate);
+ //arbitrary range of 2 bit handle range (1-4
+ serviceChangedChar.setValue(QByteArray::fromHex("0104"));
+
+ const QLowEnergyDescriptorData clientConfig(
+ QBluetoothUuid::ClientCharacteristicConfiguration,
+ QByteArray(2, 0));
+ serviceChangedChar.addDescriptor(clientConfig);
+ gattServiceData.addCharacteristic(serviceChangedChar);
+
+ service = addServiceHelper(gattServiceData);
+ if (service)
+ service->setParent(q);
+}
+
void QLowEnergyControllerPrivate::l2cpConnected()
{
Q_Q(QLowEnergyController);
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index 5811376b..5c680c3b 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -147,6 +147,8 @@ public:
QLowEnergyHandle handle);
QLowEnergyDescriptor descriptorForHandle(
QLowEnergyHandle handle);
+ QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service);
+
quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
const QByteArray &value,
@@ -416,6 +418,7 @@ private:
void restartRequestTimer();
void establishL2cpClientSocket();
+ void createServicesForCentralIfRequired();
private slots:
void l2cpConnected();