summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2016-11-08 16:47:51 +0100
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2016-11-09 14:15:40 +0000
commit8c2f88f2294ea871e374ef1a13ea4793854bd214 (patch)
tree5bea901e0caea907838c20812b955387b8531803 /src
parent85a626e83fa90bfae09be28e32c957f6bab2d861 (diff)
Emit descriptorWritten for notification/indication enabled/disabled
From CoreBluetooth's point of view - this is just a callback, not a descriptor write request (they even consider all descriptors immutable in peripheral), but for Qt it should be a descriptor write operation, and we must emit a signal. Oh, and set endHandle correctly on a LE service object! Change-Id: I71922507a6ece987ad8b5c317ef618301ae240c2 Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/osx/osxbtnotifier_p.h1
-rw-r--r--src/bluetooth/osx/osxbtperipheralmanager.mm14
-rw-r--r--src/bluetooth/qlowenergycontroller_osx.mm47
-rw-r--r--src/bluetooth/qlowenergycontroller_osx_p.h1
4 files changed, 61 insertions, 2 deletions
diff --git a/src/bluetooth/osx/osxbtnotifier_p.h b/src/bluetooth/osx/osxbtnotifier_p.h
index 0ffd7f51..47ee6ba1 100644
--- a/src/bluetooth/osx/osxbtnotifier_p.h
+++ b/src/bluetooth/osx/osxbtnotifier_p.h
@@ -88,6 +88,7 @@ Q_SIGNALS:
void characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value);
void descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value);
void descriptorWritten(QLowEnergyHandle descHandle, const QByteArray &value);
+ void notificationEnabled(QLowEnergyHandle charHandle, bool enabled);
void LEnotSupported();
void CBManagerError(QBluetoothDeviceDiscoveryAgent::Error error);
diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm
index a44fb95c..1a461be9 100644
--- a/src/bluetooth/osx/osxbtperipheralmanager.mm
+++ b/src/bluetooth/osx/osxbtperipheralmanager.mm
@@ -236,6 +236,8 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
services.push_back(newCBService);
serviceIndex[data.uuid()] = newCBService;
+ newQtService->endHandle = lastHandle;
+
return newQtService;
}
@@ -357,6 +359,8 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
return;
}
+ emit notifier->characteristicWritten(charHandle, value);
+
const auto nsData = mutable_data_from_bytearray(value);
charValues[charHandle] = nsData;
// We copy data here: sending update requests is async (see sendUpdateRequests),
@@ -480,6 +484,9 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
return;
[self addConnectedCentral:central];
+
+ if (const auto handle = charMap.key(characteristic))
+ emit notifier->notificationEnabled(handle, true);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central
@@ -491,6 +498,11 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
return;
[self removeConnectedCentral:central];
+
+ if (![connectedCentrals count]) {
+ if (const auto handle = charMap.key(characteristic))
+ emit notifier->notificationEnabled(handle, false);
+ }
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
@@ -757,7 +769,7 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data)
valueRanges[declHandle] = ValueRange(ch.minimumValueLength(), ch.maximumValueLength());
// QT part:
QLowEnergyServicePrivate::CharData charData;
- charData.valueHandle = ++lastHandle;
+ charData.valueHandle = declHandle;
charData.uuid = ch.uuid();
charData.properties = ch.properties();
charData.value = ch.value();
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm
index 6e85e630..f2b7b0bd 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_osx.mm
@@ -444,6 +444,49 @@ void QLowEnergyControllerPrivateOSX::_q_descriptorWritten(QLowEnergyHandle dHand
emit service->descriptorWritten(qtDescriptor, value);
}
+void QLowEnergyControllerPrivateOSX::_q_notificationEnabled(QLowEnergyHandle charHandle,
+ bool enabled)
+{
+ // CoreBluetooth in peripheral role does not allow mutable descriptors,
+ // in central we can only call setNotification:enabled/disabled.
+ // But from Qt API's point of view, a central has to write into
+ // client characteristic configuration descriptor. So here we emulate
+ // such a write (we cannot say if it's a notification or indication and
+ // report as both).
+
+ Q_ASSERT_X(role == QLowEnergyController::PeripheralRole, Q_FUNC_INFO,
+ "controller has an invalid role, 'peripheral' expected");
+ Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)");
+
+ const QLowEnergyCharacteristic qtChar(characteristicForHandle(charHandle));
+ if (!qtChar.isValid()) {
+ qCWarning(QT_BT_OSX) << "unknown characteristic" << charHandle;
+ return;
+ }
+
+ const QLowEnergyDescriptor qtDescriptor =
+ qtChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
+ if (!qtDescriptor.isValid()) {
+ qCWarning(QT_BT_OSX) << "characteristic" << charHandle
+ << "does not have a client characteristic "
+ "descriptor";
+ return;
+ }
+
+ ServicePrivate service(serviceForHandle(charHandle));
+ if (service.data()) {
+ // It's a 16-bit value, the least significant bit is for notifications,
+ // the next one - for indications (thus 1 means notifications enabled,
+ // 2 - indications enabled).
+ // 3 is the maximum value and it means both enabled.
+ QByteArray value(2, 0);
+ if (enabled)
+ value[0] = 3;
+ updateValueOfDescriptor(charHandle, qtDescriptor.handle(), value, false);
+ emit service->descriptorWritten(qtDescriptor, value);
+ }
+}
+
void QLowEnergyControllerPrivateOSX::_q_LEnotSupported()
{
// Report as an error. But this should not be possible
@@ -713,7 +756,7 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
[manager write:newValueCopy charHandle:charHandle];
});
#else
- qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
+ qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
#endif
}
}
@@ -950,6 +993,8 @@ bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotif
this, &QLowEnergyControllerPrivateOSX::_q_descriptorRead);
ok = ok && connect(notifier, &LECBManagerNotifier::descriptorWritten,
this, &QLowEnergyControllerPrivateOSX::_q_descriptorWritten);
+ ok = ok && connect(notifier, &LECBManagerNotifier::notificationEnabled,
+ this, &QLowEnergyControllerPrivateOSX::_q_notificationEnabled);
ok = ok && connect(notifier, &LECBManagerNotifier::LEnotSupported,
this, &QLowEnergyControllerPrivateOSX::_q_LEnotSupported);
ok = ok && connect(notifier, SIGNAL(CBManagerError(QLowEnergyController::Error)),
diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_osx_p.h
index b7399ed7..5cceb9e6 100644
--- a/src/bluetooth/qlowenergycontroller_osx_p.h
+++ b/src/bluetooth/qlowenergycontroller_osx_p.h
@@ -104,6 +104,7 @@ private Q_SLOTS:
void _q_characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value);
void _q_descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value);
void _q_descriptorWritten(QLowEnergyHandle charHandle, const QByteArray &value);
+ void _q_notificationEnabled(QLowEnergyHandle charHandle, bool enabled);
void _q_LEnotSupported();
void _q_CBManagerError(QLowEnergyController::Error error);