diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-23 19:05:57 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-27 09:04:16 +0000 |
commit | 9cbd63e8155779f866da1154ed6016423bbe5265 (patch) | |
tree | c95a14764b66bd6cc8633eb0e22d87d8a8fcc29d /src/bluetooth/qlowenergycontroller_win.cpp | |
parent | 15b795c62681aa3cb5a0187434503b83a439e390 (diff) |
Windows: Implement the characteristic writing
Writing function can be blocked some time if a remote
device is not connected or go out from the range.
Change-Id: Ia887dccf4c2c61693b04c35f2c092ac3b11e596a
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/qlowenergycontroller_win.cpp')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_win.cpp | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/src/bluetooth/qlowenergycontroller_win.cpp b/src/bluetooth/qlowenergycontroller_win.cpp index d2374f96..0518177c 100644 --- a/src/bluetooth/qlowenergycontroller_win.cpp +++ b/src/bluetooth/qlowenergycontroller_win.cpp @@ -278,6 +278,35 @@ static QByteArray getGattCharacteristicValue( } } +static void setGattCharacteristicValue( + HANDLE hService, PBTH_LE_GATT_CHARACTERISTIC gattCharacteristic, + const QByteArray &value, DWORD flags, int *systemErrorCode) +{ + if (!gattFunctionsResolved) { + *systemErrorCode = ERROR_NOT_SUPPORTED; + return; + } + + QByteArray valueBuffer; + QDataStream out(&valueBuffer, QIODevice::WriteOnly); + ULONG dataSize = value.size(); + out.writeRawData(reinterpret_cast<const char *>(&dataSize), sizeof(dataSize)); + out.writeRawData(value.constData(), value.size()); + + BTH_LE_GATT_RELIABLE_WRITE_CONTEXT reliableWriteContext = 0; + + if (::BluetoothGATTSetCharacteristicValue( + hService, + gattCharacteristic, + reinterpret_cast<PBTH_LE_GATT_CHARACTERISTIC_VALUE>(valueBuffer.data()), + reliableWriteContext, + flags) != S_OK) { + *systemErrorCode = ::GetLastError(); + } else { + *systemErrorCode = NO_ERROR; + } +} + static QVector<BTH_LE_GATT_DESCRIPTOR> enumerateGattDescriptors( HANDLE hService, PBTH_LE_GATT_CHARACTERISTIC gattCharacteristic, int *systemErrorCode) { @@ -689,12 +718,58 @@ void QLowEnergyControllerPrivate::readCharacteristic( } void QLowEnergyControllerPrivate::writeCharacteristic( - const QSharedPointer<QLowEnergyServicePrivate> /*service*/, - const QLowEnergyHandle /*charHandle*/, - const QByteArray &/*newValue*/, - bool /*writeWithResponse*/) + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + bool writeWithResponse) { + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + int systemErrorCode = NO_ERROR; + + const HANDLE hService = openSystemService( + service->uuid, QIODevice::ReadWrite, &systemErrorCode); + if (systemErrorCode != NO_ERROR) { + qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service->uuid.toString() + << ":" << qt_error_string(systemErrorCode); + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + + BTH_LE_GATT_CHARACTERISTIC gattCharacteristic = recoverNativeLeGattCharacteristic( + service->startHandle, charHandle, charDetails); + + const DWORD flags = writeWithResponse + ? BLUETOOTH_GATT_FLAG_NONE + : BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE; + + // TODO: If a device is not connected, this function will block + // for some time. So, need to re-implement of writeCharacteristic() + // with use QFutureWatcher. + setGattCharacteristicValue(hService, &gattCharacteristic, + newValue, flags, &systemErrorCode); + + if (systemErrorCode != NO_ERROR) { + qCWarning(QT_BT_WINDOWS) << "Unable to set value for characteristic" + << charDetails.uuid.toString() + << "of the service" << service->uuid.toString() + << ":" << qt_error_string(systemErrorCode); + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + + updateValueOfCharacteristic(charHandle, newValue, false); + + if (writeWithResponse) { + QLowEnergyCharacteristic ch(service, charHandle); + emit service->characteristicWritten(ch, newValue); + } } void QLowEnergyControllerPrivate::readDescriptor( |