summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qlowenergycontroller_win.cpp
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2015-10-23 19:05:57 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2015-10-27 09:04:16 +0000
commit9cbd63e8155779f866da1154ed6016423bbe5265 (patch)
treec95a14764b66bd6cc8633eb0e22d87d8a8fcc29d /src/bluetooth/qlowenergycontroller_win.cpp
parent15b795c62681aa3cb5a0187434503b83a439e390 (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.cpp83
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(