[go: nahoru, domu]

blob: 85532b7ce82446c92ff13e1d6a0e54f070dadb6e [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"
16#include "device/bluetooth/bluetooth_remote_gatt_service_winrt.h"
17#include "device/bluetooth/event_utils_winrt.h"
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1618
19namespace device {
20
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5721namespace {
22
Reilly Grantdc08cac2018-12-07 01:11:0123using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5724using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4525 GattCommunicationStatus;
26using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
27 GattCommunicationStatus_Success;
28using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult;
29using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
30 GattWriteResult;
31using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5732 IGattDescriptor;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4533using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0134 IGattDescriptor2;
Jan Wilken Dörried0a3dc62018-08-06 10:15:4535using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
36 IGattReadResult;
37using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Reilly Grantdc08cac2018-12-07 01:11:0138 IGattReadResult2;
39using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
Jan Wilken Dörried0a3dc62018-08-06 10:15:4540 IGattWriteResult;
41using ABI::Windows::Foundation::IAsyncOperation;
42using ABI::Windows::Storage::Streams::IBuffer;
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5743using Microsoft::WRL::ComPtr;
44
45} // namespace
46
47// static
48std::unique_ptr<BluetoothRemoteGattDescriptorWinrt>
49BluetoothRemoteGattDescriptorWinrt::Create(
50 BluetoothRemoteGattCharacteristic* characteristic,
51 ComPtr<IGattDescriptor> descriptor) {
52 DCHECK(descriptor);
53 GUID guid;
54 HRESULT hr = descriptor->get_Uuid(&guid);
55 if (FAILED(hr)) {
56 VLOG(2) << "Getting UUID failed: " << logging::SystemErrorCodeToString(hr);
57 return nullptr;
58 }
59
60 uint16_t attribute_handle;
61 hr = descriptor->get_AttributeHandle(&attribute_handle);
62 if (FAILED(hr)) {
63 VLOG(2) << "Getting AttributeHandle failed: "
64 << logging::SystemErrorCodeToString(hr);
65 return nullptr;
66 }
67
68 return base::WrapUnique(new BluetoothRemoteGattDescriptorWinrt(
69 characteristic, std::move(descriptor), BluetoothUUID(guid),
70 attribute_handle));
71}
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1672
73BluetoothRemoteGattDescriptorWinrt::~BluetoothRemoteGattDescriptorWinrt() =
74 default;
75
76std::string BluetoothRemoteGattDescriptorWinrt::GetIdentifier() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5777 return identifier_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1678}
79
80BluetoothUUID BluetoothRemoteGattDescriptorWinrt::GetUUID() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5781 return uuid_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1682}
83
84BluetoothGattCharacteristic::Permissions
85BluetoothRemoteGattDescriptorWinrt::GetPermissions() const {
86 NOTIMPLEMENTED();
87 return BluetoothGattCharacteristic::Permissions();
88}
89
90const std::vector<uint8_t>& BluetoothRemoteGattDescriptorWinrt::GetValue()
91 const {
92 return value_;
93}
94
95BluetoothRemoteGattCharacteristic*
96BluetoothRemoteGattDescriptorWinrt::GetCharacteristic() const {
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:5797 return characteristic_;
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:1698}
99
100void BluetoothRemoteGattDescriptorWinrt::ReadRemoteDescriptor(
danakjfcba225f2019-04-23 17:06:49101 ValueCallback callback,
danakj056b93572019-04-23 16:04:45102 ErrorCallback error_callback) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45103 if (pending_read_callbacks_ || pending_write_callbacks_) {
104 base::ThreadTaskRunnerHandle::Get()->PostTask(
105 FROM_HERE,
danakj056b93572019-04-23 16:04:45106 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45107 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
108 return;
109 }
110
111 ComPtr<IAsyncOperation<GattReadResult*>> read_value_op;
Reilly Grantdc08cac2018-12-07 01:11:01112 HRESULT hr = descriptor_->ReadValueWithCacheModeAsync(
113 BluetoothCacheMode_Uncached, &read_value_op);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45114 if (FAILED(hr)) {
Reilly Grantdc08cac2018-12-07 01:11:01115 VLOG(2) << "GattDescriptor::ReadValueWithCacheModeAsync failed: "
Jan Wilken Dörried0a3dc62018-08-06 10:15:45116 << logging::SystemErrorCodeToString(hr);
117 base::ThreadTaskRunnerHandle::Get()->PostTask(
118 FROM_HERE,
danakj056b93572019-04-23 16:04:45119 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45120 BluetoothRemoteGattService::GATT_ERROR_FAILED));
121 return;
122 }
123
Reilly Grant4bc137c2018-12-13 22:55:15124 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45125 std::move(read_value_op),
126 base::BindOnce(&BluetoothRemoteGattDescriptorWinrt::OnReadValue,
127 weak_ptr_factory_.GetWeakPtr()));
128
129 if (FAILED(hr)) {
130 VLOG(2) << "PostAsyncResults failed: "
131 << logging::SystemErrorCodeToString(hr);
132 base::ThreadTaskRunnerHandle::Get()->PostTask(
133 FROM_HERE,
danakj056b93572019-04-23 16:04:45134 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45135 BluetoothRemoteGattService::GATT_ERROR_FAILED));
136 return;
137 }
138
danakj056b93572019-04-23 16:04:45139 pending_read_callbacks_ = std::make_unique<PendingReadCallbacks>(
danakjfcba225f2019-04-23 17:06:49140 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16141}
142
143void BluetoothRemoteGattDescriptorWinrt::WriteRemoteDescriptor(
144 const std::vector<uint8_t>& value,
danakjfcba225f2019-04-23 17:06:49145 base::OnceClosure callback,
danakj056b93572019-04-23 16:04:45146 ErrorCallback error_callback) {
Jan Wilken Dörried0a3dc62018-08-06 10:15:45147 if (pending_read_callbacks_ || pending_write_callbacks_) {
148 base::ThreadTaskRunnerHandle::Get()->PostTask(
149 FROM_HERE,
danakj056b93572019-04-23 16:04:45150 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45151 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
152 return;
153 }
154
155 ComPtr<IGattDescriptor2> descriptor_2;
156 HRESULT hr = descriptor_.As(&descriptor_2);
157 if (FAILED(hr)) {
158 VLOG(2) << "As IGattDescriptor2 failed: "
159 << logging::SystemErrorCodeToString(hr);
160 base::ThreadTaskRunnerHandle::Get()->PostTask(
161 FROM_HERE,
danakj056b93572019-04-23 16:04:45162 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45163 BluetoothRemoteGattService::GATT_ERROR_FAILED));
164 return;
165 }
166
167 ComPtr<IBuffer> buffer;
168 hr = base::win::CreateIBufferFromData(value.data(), value.size(), &buffer);
169 if (FAILED(hr)) {
170 VLOG(2) << "base::win::CreateIBufferFromData failed: "
171 << logging::SystemErrorCodeToString(hr);
172 base::ThreadTaskRunnerHandle::Get()->PostTask(
173 FROM_HERE,
danakj056b93572019-04-23 16:04:45174 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45175 BluetoothRemoteGattService::GATT_ERROR_FAILED));
176 return;
177 }
178
179 ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
180 hr = descriptor_2->WriteValueWithResultAsync(buffer.Get(), &write_value_op);
181 if (FAILED(hr)) {
182 VLOG(2) << "GattDescriptor::WriteValueWithResultAsync failed: "
183 << logging::SystemErrorCodeToString(hr);
184 base::ThreadTaskRunnerHandle::Get()->PostTask(
185 FROM_HERE,
danakj056b93572019-04-23 16:04:45186 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45187 BluetoothRemoteGattService::GATT_ERROR_FAILED));
188 return;
189 }
190
Reilly Grant4bc137c2018-12-13 22:55:15191 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45192 std::move(write_value_op),
193 base::BindOnce(
194 &BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult,
195 weak_ptr_factory_.GetWeakPtr()));
196
197 if (FAILED(hr)) {
198 VLOG(2) << "PostAsyncResults failed: "
199 << logging::SystemErrorCodeToString(hr);
200 base::ThreadTaskRunnerHandle::Get()->PostTask(
201 FROM_HERE,
danakj056b93572019-04-23 16:04:45202 base::BindOnce(std::move(error_callback),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45203 BluetoothRemoteGattService::GATT_ERROR_FAILED));
204 return;
205 }
206
danakj056b93572019-04-23 16:04:45207 pending_write_callbacks_ = std::make_unique<PendingWriteCallbacks>(
danakjfcba225f2019-04-23 17:06:49208 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16209}
210
Jan Wilken Dörried0a3dc62018-08-06 10:15:45211IGattDescriptor* BluetoothRemoteGattDescriptorWinrt::GetDescriptorForTesting() {
212 return descriptor_.Get();
213}
214
215BluetoothRemoteGattDescriptorWinrt::PendingReadCallbacks::PendingReadCallbacks(
216 ValueCallback callback,
217 ErrorCallback error_callback)
218 : callback(std::move(callback)),
219 error_callback(std::move(error_callback)) {}
220
221BluetoothRemoteGattDescriptorWinrt::PendingReadCallbacks::
222 ~PendingReadCallbacks() = default;
223
224BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
225 PendingWriteCallbacks(base::OnceClosure callback,
226 ErrorCallback error_callback)
227 : callback(std::move(callback)),
228 error_callback(std::move(error_callback)) {}
229
230BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
231 ~PendingWriteCallbacks() = default;
232
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57233BluetoothRemoteGattDescriptorWinrt::BluetoothRemoteGattDescriptorWinrt(
234 BluetoothRemoteGattCharacteristic* characteristic,
235 Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
236 GenericAttributeProfile::IGattDescriptor>
237 descriptor,
238 BluetoothUUID uuid,
239 uint16_t attribute_handle)
240 : characteristic_(characteristic),
241 descriptor_(std::move(descriptor)),
242 uuid_(std::move(uuid)),
243 identifier_(base::StringPrintf("%s/%s_%04x",
244 characteristic_->GetIdentifier().c_str(),
245 uuid_.value().c_str(),
Jan Wilken Dörried0a3dc62018-08-06 10:15:45246 attribute_handle)),
247 weak_ptr_factory_(this) {}
248
249void BluetoothRemoteGattDescriptorWinrt::OnReadValue(
250 ComPtr<IGattReadResult> read_result) {
251 DCHECK(pending_read_callbacks_);
252 auto pending_read_callbacks = std::move(pending_read_callbacks_);
253
254 if (!read_result) {
danakj056b93572019-04-23 16:04:45255 std::move(pending_read_callbacks->error_callback)
256 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45257 return;
258 }
259
260 GattCommunicationStatus status;
261 HRESULT hr = read_result->get_Status(&status);
262 if (FAILED(hr)) {
263 VLOG(2) << "Getting GATT Communication Status failed: "
264 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45265 std::move(pending_read_callbacks->error_callback)
266 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45267 return;
268 }
269
270 if (status != GattCommunicationStatus_Success) {
271 VLOG(2) << "Unexpected GattCommunicationStatus: " << status;
272 ComPtr<IGattReadResult2> read_result_2;
273 hr = read_result.As(&read_result_2);
274 if (FAILED(hr)) {
275 VLOG(2) << "As IGattReadResult2 failed: "
276 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45277 std::move(pending_read_callbacks->error_callback)
278 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45279 return;
280 }
281
danakj056b93572019-04-23 16:04:45282 std::move(pending_read_callbacks->error_callback)
283 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
284 read_result_2.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45285 return;
286 }
287
288 ComPtr<IBuffer> value;
289 hr = read_result->get_Value(&value);
290 if (FAILED(hr)) {
291 VLOG(2) << "Getting Descriptor Value failed: "
292 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45293 std::move(pending_read_callbacks->error_callback)
294 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45295 return;
296 }
297
298 uint8_t* data = nullptr;
299 uint32_t length = 0;
300 hr = base::win::GetPointerToBufferData(value.Get(), &data, &length);
301 if (FAILED(hr)) {
302 VLOG(2) << "Getting Pointer To Buffer Data failed: "
303 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45304 std::move(pending_read_callbacks->error_callback)
305 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45306 return;
307 }
308
309 value_.assign(data, data + length);
danakjfcba225f2019-04-23 17:06:49310 std::move(pending_read_callbacks->callback).Run(value_);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45311}
312
313void BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult(
314 ComPtr<IGattWriteResult> write_result) {
315 DCHECK(pending_write_callbacks_);
316 auto pending_write_callbacks = std::move(pending_write_callbacks_);
317
318 if (!write_result) {
danakj056b93572019-04-23 16:04:45319 std::move(pending_write_callbacks->error_callback)
320 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45321 return;
322 }
323
324 GattCommunicationStatus status;
325 HRESULT hr = write_result->get_Status(&status);
326 if (FAILED(hr)) {
327 VLOG(2) << "Getting GATT Communication Status failed: "
328 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45329 std::move(pending_write_callbacks->error_callback)
330 .Run(BluetoothGattService::GATT_ERROR_FAILED);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45331 return;
332 }
333
334 if (status != GattCommunicationStatus_Success) {
335 VLOG(2) << "Unexpected GattCommunicationStatus: " << status;
danakj056b93572019-04-23 16:04:45336 std::move(pending_write_callbacks->error_callback)
337 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
338 write_result.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45339 return;
340 }
341
342 std::move(pending_write_callbacks->callback).Run();
343}
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57344
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16345} // namespace device