summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Buhr <andreas.buhr@qt.io>2021-05-25 13:37:04 +0200
committerAndreas Buhr <andreas.buhr@qt.io>2021-06-03 11:23:50 +0200
commit3b481365afa02d044b65b8f7bf1b5db4143ddcb7 (patch)
treed305b64a2304ac1d86ad02dafb6335d09251e753
parent4b52a0b6e8feefdaf823df91eb9a5123b14005d5 (diff)
QLowEnergyController: ATT-MTU backend on Windows
In c5a5d1c9105f1fe1974b05d8276e041f2dc52bd6 an API to obtain the ATT-MTU size was introduced. This was unimplemented in the Windows backend so far. This patch adds an implementation for Windows. Fixes: QTBUG-93827 Change-Id: If8ea6d7bc514220496bd3e005694c69f5b839387 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp85
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h7
2 files changed, 89 insertions, 3 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index 75ec528c..c2981b1d 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -73,6 +73,7 @@ using namespace ABI::Windows::Storage::Streams;
QT_BEGIN_NAMESPACE
typedef ITypedEventHandler<BluetoothLEDevice *, IInspectable *> StatusHandler;
+typedef ITypedEventHandler<GattSession *, IInspectable *> MtuHandler;
typedef ITypedEventHandler<GattCharacteristic *, GattValueChangedEventArgs *> ValueChangedHandler;
typedef GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConfigDescriptorResult;
typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult;
@@ -483,6 +484,36 @@ void QLowEnergyControllerPrivateWinRT::connectToDevice()
setState(QLowEnergyController::UnconnectedState);
return;
}
+
+ // get GattSession: 1. get device id
+ ComPtr<IBluetoothLEDevice4> device4;
+ hr = mDevice.As(&device4);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return );
+
+ ComPtr<IBluetoothDeviceId> deviceId;
+ hr = device4->get_BluetoothDeviceId(&deviceId);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not get bluetooth device id", return )
+
+ // get GattSession: 2. get session statics
+ ComPtr<IGattSessionStatics> sessionStatics;
+ hr = GetActivationFactory(
+ HString::MakeReference(
+ RuntimeClass_Windows_Devices_Bluetooth_GenericAttributeProfile_GattSession)
+ .Get(),
+ &sessionStatics);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain GattSession statics", return )
+
+ // get GattSession: 3. get session
+ ComPtr<IAsyncOperation<GattSession *>> gattSessionFromIdOperation;
+ hr = sessionStatics->FromDeviceIdAsync(deviceId.Get(), &gattSessionFromIdOperation);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not get GattSession from id", return )
+ hr = QWinRTFunctions::await(gattSessionFromIdOperation, mGattSession.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not complete Gatt session acquire", return )
+
+ // subscribe to changed event
+ registerForMtuChanges();
+
BluetoothConnectionStatus status;
hr = mDevice->get_ConnectionStatus(&status);
CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain device's connection status", return)
@@ -507,7 +538,9 @@ void QLowEnergyControllerPrivateWinRT::disconnectFromDevice()
setState(QLowEnergyController::ClosingState);
unregisterFromValueChanges();
unregisterFromStatusChanges();
+ unregisterFromMtuChanges();
mAbortPending = true;
+ mGattSession = nullptr;
mDevice = nullptr;
setState(QLowEnergyController::UnconnectedState);
emit q->disconnected();
@@ -622,6 +655,18 @@ HRESULT QLowEnergyControllerPrivateWinRT::onValueChange(IGattCharacteristic *cha
emit characteristicChanged(handle, byteArrayFromBuffer(buffer));
return S_OK;
}
+HRESULT QLowEnergyControllerPrivateWinRT::onMtuChange(IGattSession *session, IInspectable *args)
+{
+ qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
+ if (session != mGattSession.Get()) {
+ qCWarning(QT_BT_WINDOWS) << "Got MTU changed event for wrong GattSession.";
+ return S_OK;
+ }
+
+ Q_Q(QLowEnergyController);
+ emit q->mtuChanged(mtu());
+ return S_OK;
+}
bool QLowEnergyControllerPrivateWinRT::registerForStatusChanges()
{
@@ -634,7 +679,7 @@ bool QLowEnergyControllerPrivateWinRT::registerForStatusChanges()
hr = mDevice->add_ConnectionStatusChanged(
Callback<StatusHandler>(this, &QLowEnergyControllerPrivateWinRT::onStatusChange).Get(),
&mStatusChangedToken);
- RETURN_IF_FAILED("Could not add status callback on Xaml thread", return false)
+ RETURN_IF_FAILED("Could not add status callback", return false)
return true;
}
@@ -647,6 +692,30 @@ void QLowEnergyControllerPrivateWinRT::unregisterFromStatusChanges()
}
}
+bool QLowEnergyControllerPrivateWinRT::registerForMtuChanges()
+{
+ if (!mDevice || !mGattSession)
+ return false;
+
+ qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
+
+ HRESULT hr;
+ hr = mGattSession->add_MaxPduSizeChanged(
+ Callback<MtuHandler>(this, &QLowEnergyControllerPrivateWinRT::onMtuChange).Get(),
+ &mMtuChangedToken);
+ RETURN_IF_FAILED("Could not add MTU callback", return false)
+ return true;
+}
+
+void QLowEnergyControllerPrivateWinRT::unregisterFromMtuChanges()
+{
+ qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
+ if (mDevice && mGattSession && mMtuChangedToken.value) {
+ mGattSession->remove_MaxPduSizeChanged(mMtuChangedToken);
+ mMtuChangedToken.value = 0;
+ }
+}
+
HRESULT QLowEnergyControllerPrivateWinRT::onStatusChange(IBluetoothLEDevice *dev, IInspectable *)
{
Q_Q(QLowEnergyController);
@@ -663,6 +732,8 @@ HRESULT QLowEnergyControllerPrivateWinRT::onStatusChange(IBluetoothLEDevice *dev
invalidateServices();
unregisterFromValueChanges();
unregisterFromStatusChanges();
+ unregisterFromMtuChanges();
+ mGattSession = nullptr;
mDevice = nullptr;
setError(QLowEnergyController::RemoteHostClosedError);
setState(QLowEnergyController::UnconnectedState);
@@ -1489,8 +1560,16 @@ void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnerg
int QLowEnergyControllerPrivateWinRT::mtu() const
{
- // not supported yet
- return -1;
+ uint16_t mtu = 23;
+ if (!mGattSession) {
+ qCDebug(QT_BT_WINDOWS) << "mtu queried before GattSession available. Using default mtu.";
+ return mtu;
+ }
+
+ HRESULT hr = mGattSession->get_MaxPduSize(&mtu);
+ RETURN_IF_FAILED("could not obtain MTU size", return mtu);
+ qCDebug(QT_BT_WINDOWS) << "mtu determined to be" << mtu;
+ return mtu;
}
void QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged(
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
index 4cb45c54..7e6c8823 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -143,7 +143,10 @@ private:
bool mAbortPending = false;
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession>
+ mGattSession;
EventRegistrationToken mStatusChangedToken;
+ EventRegistrationToken mMtuChangedToken;
struct ValueChangedEntry {
ValueChangedEntry() {}
ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c,
@@ -165,6 +168,10 @@ private:
void unregisterFromValueChanges();
HRESULT onValueChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic *characteristic,
ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattValueChangedEventArgs *args);
+ HRESULT onMtuChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession *session,
+ IInspectable *args);
+ bool registerForMtuChanges();
+ void unregisterFromMtuChanges();
bool registerForStatusChanges();
void unregisterFromStatusChanges();