[go: nahoru, domu]

blob: 7b8450652e8e0a2e91cf52378866f65d68cae1fe [file] [log] [blame]
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:161// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.h"
6
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:577#include <utility>
8
Sebastien Marchand6d0558fd2019-01-25 16:49:379#include "base/bind.h"
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1610#include "base/logging.h"
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5711#include "base/memory/ptr_util.h"
12#include "base/strings/stringprintf.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4513#include "base/threading/thread_task_runner_handle.h"
Reilly Grant4bc137c2018-12-13 22:55:1514#include "base/win/post_async_results.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4515#include "base/win/winrt_storage_util.h"
Martin Kreichgauerc8a70012020-01-31 01:08:5216#include "components/device_event_log/device_event_log.h"
Jan Wilken Dörried0a3dc62018-08-06 10:15:4517#include "device/bluetooth/bluetooth_remote_gatt_service_winrt.h"
18#include "device/bluetooth/event_utils_winrt.h"
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1619
20namespace device {
21
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5722namespace {
23
Reilly Grantdc08cac2018-12-07 01:11:0124using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5725using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4526 GattCommunicationStatus;
27using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
28 GattCommunicationStatus_Success;
29using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult;
30using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
31 GattWriteResult;
32using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5733 IGattDescriptor;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4534using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0135 IGattDescriptor2;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4536using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
37 IGattReadResult;
38using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0139 IGattReadResult2;
40using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4541 IGattWriteResult;
42using ABI::Windows::Foundation::IAsyncOperation;
43using ABI::Windows::Storage::Streams::IBuffer;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5744using Microsoft::WRL::ComPtr;
45
46} // namespace
47
48// static
49std::unique_ptr<BluetoothRemoteGattDescriptorWinrt>
50BluetoothRemoteGattDescriptorWinrt::Create(
51 BluetoothRemoteGattCharacteristic* characteristic,
52 ComPtr<IGattDescriptor> descriptor) {
53 DCHECK(descriptor);
54 GUID guid;
55 HRESULT hr = descriptor->get_Uuid(&guid);
56 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:5257 BLUETOOTH_LOG(ERROR) << "Getting UUID failed: "
58 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5759 return nullptr;
60 }
61
62 uint16_t attribute_handle;
63 hr = descriptor->get_AttributeHandle(&attribute_handle);
64 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:5265 BLUETOOTH_LOG(ERROR) << "Getting AttributeHandle failed: "
66 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5767 return nullptr;
68 }
69
70 return base::WrapUnique(new BluetoothRemoteGattDescriptorWinrt(
71 characteristic, std::move(descriptor), BluetoothUUID(guid),
72 attribute_handle));
73}
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1674
75BluetoothRemoteGattDescriptorWinrt::~BluetoothRemoteGattDescriptorWinrt() =
76 default;
77
78std::string BluetoothRemoteGattDescriptorWinrt::GetIdentifier() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5779 return identifier_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1680}
81
82BluetoothUUID BluetoothRemoteGattDescriptorWinrt::GetUUID() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5783 return uuid_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1684}
85
86BluetoothGattCharacteristic::Permissions
87BluetoothRemoteGattDescriptorWinrt::GetPermissions() const {
88 NOTIMPLEMENTED();
89 return BluetoothGattCharacteristic::Permissions();
90}
91
92const std::vector<uint8_t>& BluetoothRemoteGattDescriptorWinrt::GetValue()
93 const {
94 return value_;
95}
96
97BluetoothRemoteGattCharacteristic*
98BluetoothRemoteGattDescriptorWinrt::GetCharacteristic() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5799 return characteristic_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16100}
101
102void BluetoothRemoteGattDescriptorWinrt::ReadRemoteDescriptor(
danakjfcba225f2019-04-23 17:06:49103 ValueCallback callback,
danakj056b93572019-04-23 16:04:45104 ErrorCallback error_callback) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45105 if (pending_read_callbacks_ || pending_write_callbacks_) {
106 base::ThreadTaskRunnerHandle::Get()->PostTask(
107 FROM_HERE,
danakj056b93572019-04-23 16:04:45108 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45109 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
110 return;
111 }
112
113 ComPtr<IAsyncOperation<GattReadResult*>> read_value_op;
Reilly Grantdc08cac2018-12-07 01:11:01114 HRESULT hr = descriptor_->ReadValueWithCacheModeAsync(
115 BluetoothCacheMode_Uncached, &read_value_op);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45116 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52117 BLUETOOTH_LOG(ERROR)
118 << "GattDescriptor::ReadValueWithCacheModeAsync failed: "
119 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45120 base::ThreadTaskRunnerHandle::Get()->PostTask(
121 FROM_HERE,
danakj056b93572019-04-23 16:04:45122 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45123 BluetoothRemoteGattService::GATT_ERROR_FAILED));
124 return;
125 }
126
Reilly Grant4bc137c2018-12-13 22:55:15127 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45128 std::move(read_value_op),
129 base::BindOnce(&BluetoothRemoteGattDescriptorWinrt::OnReadValue,
130 weak_ptr_factory_.GetWeakPtr()));
131
132 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52133 BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
134 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45135 base::ThreadTaskRunnerHandle::Get()->PostTask(
136 FROM_HERE,
danakj056b93572019-04-23 16:04:45137 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45138 BluetoothRemoteGattService::GATT_ERROR_FAILED));
139 return;
140 }
141
danakj056b93572019-04-23 16:04:45142 pending_read_callbacks_ = std::make_unique<PendingReadCallbacks>(
danakjfcba225f2019-04-23 17:06:49143 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16144}
145
146void BluetoothRemoteGattDescriptorWinrt::WriteRemoteDescriptor(
147 const std::vector<uint8_t>& value,
danakjfcba225f2019-04-23 17:06:49148 base::OnceClosure callback,
danakj056b93572019-04-23 16:04:45149 ErrorCallback error_callback) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45150 if (pending_read_callbacks_ || pending_write_callbacks_) {
151 base::ThreadTaskRunnerHandle::Get()->PostTask(
152 FROM_HERE,
danakj056b93572019-04-23 16:04:45153 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45154 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
155 return;
156 }
157
158 ComPtr<IGattDescriptor2> descriptor_2;
159 HRESULT hr = descriptor_.As(&descriptor_2);
160 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52161 BLUETOOTH_LOG(ERROR) << "As IGattDescriptor2 failed: "
162 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45163 base::ThreadTaskRunnerHandle::Get()->PostTask(
164 FROM_HERE,
danakj056b93572019-04-23 16:04:45165 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45166 BluetoothRemoteGattService::GATT_ERROR_FAILED));
167 return;
168 }
169
170 ComPtr<IBuffer> buffer;
171 hr = base::win::CreateIBufferFromData(value.data(), value.size(), &buffer);
172 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52173 BLUETOOTH_LOG(ERROR) << "base::win::CreateIBufferFromData failed: "
174 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45175 base::ThreadTaskRunnerHandle::Get()->PostTask(
176 FROM_HERE,
danakj056b93572019-04-23 16:04:45177 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45178 BluetoothRemoteGattService::GATT_ERROR_FAILED));
179 return;
180 }
181
182 ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
183 hr = descriptor_2->WriteValueWithResultAsync(buffer.Get(), &write_value_op);
184 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52185 BLUETOOTH_LOG(ERROR) << "GattDescriptor::WriteValueWithResultAsync failed: "
186 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45187 base::ThreadTaskRunnerHandle::Get()->PostTask(
188 FROM_HERE,
danakj056b93572019-04-23 16:04:45189 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45190 BluetoothRemoteGattService::GATT_ERROR_FAILED));
191 return;
192 }
193
Reilly Grant4bc137c2018-12-13 22:55:15194 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45195 std::move(write_value_op),
196 base::BindOnce(
197 &BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult,
198 weak_ptr_factory_.GetWeakPtr()));
199
200 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52201 BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
202 << logging::SystemErrorCodeToString(hr);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45203 base::ThreadTaskRunnerHandle::Get()->PostTask(
204 FROM_HERE,
danakj056b93572019-04-23 16:04:45205 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45206 BluetoothRemoteGattService::GATT_ERROR_FAILED));
207 return;
208 }
209
danakj056b93572019-04-23 16:04:45210 pending_write_callbacks_ = std::make_unique<PendingWriteCallbacks>(
danakjfcba225f2019-04-23 17:06:49211 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16212}
213
Jan Wilken Dörried0a3dc62018-08-06 10:15:45214IGattDescriptor* BluetoothRemoteGattDescriptorWinrt::GetDescriptorForTesting() {
215 return descriptor_.Get();
216}
217
218BluetoothRemoteGattDescriptorWinrt::PendingReadCallbacks::PendingReadCallbacks(
219 ValueCallback callback,
220 ErrorCallback error_callback)
221 : callback(std::move(callback)),
222 error_callback(std::move(error_callback)) {}
223
224BluetoothRemoteGattDescriptorWinrt::PendingReadCallbacks::
225 ~PendingReadCallbacks() = default;
226
227BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
228 PendingWriteCallbacks(base::OnceClosure callback,
229 ErrorCallback error_callback)
230 : callback(std::move(callback)),
231 error_callback(std::move(error_callback)) {}
232
233BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
234 ~PendingWriteCallbacks() = default;
235
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57236BluetoothRemoteGattDescriptorWinrt::BluetoothRemoteGattDescriptorWinrt(
237 BluetoothRemoteGattCharacteristic* characteristic,
238 Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
239 GenericAttributeProfile::IGattDescriptor>
240 descriptor,
241 BluetoothUUID uuid,
242 uint16_t attribute_handle)
243 : characteristic_(characteristic),
244 descriptor_(std::move(descriptor)),
245 uuid_(std::move(uuid)),
246 identifier_(base::StringPrintf("%s/%s_%04x",
247 characteristic_->GetIdentifier().c_str(),
248 uuid_.value().c_str(),
Jeremy Roman2b7c9502019-08-21 22:34:08249 attribute_handle)) {}
Jan Wilken Dörried0a3dc62018-08-06 10:15:45250
251void BluetoothRemoteGattDescriptorWinrt::OnReadValue(
252 ComPtr<IGattReadResult> read_result) {
253 DCHECK(pending_read_callbacks_);
254 auto pending_read_callbacks = std::move(pending_read_callbacks_);
255
256 if (!read_result) {
Martin Kreichgauerc8a70012020-01-31 01:08:52257 BLUETOOTH_LOG(ERROR)
258 << "GattDescriptor::ReadValueWithCacheModeAsync returned no result";
danakj056b93572019-04-23 16:04:45259 std::move(pending_read_callbacks->error_callback)
260 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45261 return;
262 }
263
264 GattCommunicationStatus status;
265 HRESULT hr = read_result->get_Status(&status);
266 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52267 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
268 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45269 std::move(pending_read_callbacks->error_callback)
270 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45271 return;
272 }
273
274 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52275 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
Jan Wilken Dörried0a3dc62018-08-06 10:15:45276 ComPtr<IGattReadResult2> read_result_2;
277 hr = read_result.As(&read_result_2);
278 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52279 BLUETOOTH_LOG(ERROR) << "As IGattReadResult2 failed: "
280 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45281 std::move(pending_read_callbacks->error_callback)
282 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45283 return;
284 }
285
danakj056b93572019-04-23 16:04:45286 std::move(pending_read_callbacks->error_callback)
287 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
288 read_result_2.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45289 return;
290 }
291
292 ComPtr<IBuffer> value;
293 hr = read_result->get_Value(&value);
294 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52295 BLUETOOTH_LOG(ERROR) << "Getting Descriptor Value failed: "
296 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45297 std::move(pending_read_callbacks->error_callback)
298 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45299 return;
300 }
301
302 uint8_t* data = nullptr;
303 uint32_t length = 0;
304 hr = base::win::GetPointerToBufferData(value.Get(), &data, &length);
305 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52306 BLUETOOTH_LOG(ERROR) << "Getting Pointer To Buffer Data failed: "
307 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45308 std::move(pending_read_callbacks->error_callback)
309 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45310 return;
311 }
312
313 value_.assign(data, data + length);
danakjfcba225f2019-04-23 17:06:49314 std::move(pending_read_callbacks->callback).Run(value_);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45315}
316
317void BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult(
318 ComPtr<IGattWriteResult> write_result) {
319 DCHECK(pending_write_callbacks_);
320 auto pending_write_callbacks = std::move(pending_write_callbacks_);
321
322 if (!write_result) {
Martin Kreichgauerc8a70012020-01-31 01:08:52323 BLUETOOTH_LOG(ERROR)
324 << "GattDescriptor::WriteValueWithResultAsync returned no result";
danakj056b93572019-04-23 16:04:45325 std::move(pending_write_callbacks->error_callback)
326 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45327 return;
328 }
329
330 GattCommunicationStatus status;
331 HRESULT hr = write_result->get_Status(&status);
332 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52333 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
334 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45335 std::move(pending_write_callbacks->error_callback)
336 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45337 return;
338 }
339
340 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52341 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
danakj056b93572019-04-23 16:04:45342 std::move(pending_write_callbacks->error_callback)
343 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
344 write_result.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45345 return;
346 }
347
348 std::move(pending_write_callbacks->callback).Run();
349}
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57350
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16351} // namespace device