[go: nahoru, domu]

blob: eadc38f2774c02bbf4c3e93d67cc44af194decf9 [file] [log] [blame]
Avi Drissman0db84842022-09-13 19:47:041// Copyright 2018 The Chromium Authors
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:162// 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
Avi Drissmanbb9cd022023-01-11 01:03:299#include "base/functional/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"
Sean Maher5b9af51f2022-11-21 15:32:4713#include "base/task/single_thread_task_runner.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(
Chris Mumford6627ae42021-05-03 18:54:40103 ValueCallback callback) {
104 if (pending_read_callback_ || pending_write_callbacks_) {
Sean Maher5b9af51f2022-11-21 15:32:47105 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Lei Zhang494bc8b2022-09-20 16:52:41106 FROM_HERE,
107 base::BindOnce(std::move(callback),
108 BluetoothGattService::GattErrorCode::kInProgress,
109 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45110 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);
Sean Maher5b9af51f2022-11-21 15:32:47120 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Chris Mumford6627ae42021-05-03 18:54:40121 FROM_HERE, base::BindOnce(std::move(callback),
Lei Zhang494bc8b2022-09-20 16:52:41122 BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40123 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45124 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);
Sean Maher5b9af51f2022-11-21 15:32:47135 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Chris Mumford6627ae42021-05-03 18:54:40136 FROM_HERE, base::BindOnce(std::move(callback),
Lei Zhang494bc8b2022-09-20 16:52:41137 BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40138 /*value=*/std::vector<uint8_t>()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45139 return;
140 }
141
Chris Mumford6627ae42021-05-03 18:54:40142 pending_read_callback_ = std::move(callback);
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16143}
144
145void BluetoothRemoteGattDescriptorWinrt::WriteRemoteDescriptor(
146 const std::vector<uint8_t>& value,
danakjfcba225f2019-04-23 17:06:49147 base::OnceClosure callback,
danakj056b93572019-04-23 16:04:45148 ErrorCallback error_callback) {
Chris Mumford6627ae42021-05-03 18:54:40149 if (pending_read_callback_ || pending_write_callbacks_) {
Sean Maher5b9af51f2022-11-21 15:32:47150 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45151 FROM_HERE,
danakj056b93572019-04-23 16:04:45152 base::BindOnce(std::move(error_callback),
Lei Zhang494bc8b2022-09-20 16:52:41153 BluetoothGattService::GattErrorCode::kInProgress));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45154 return;
155 }
156
157 ComPtr<IGattDescriptor2> descriptor_2;
158 HRESULT hr = descriptor_.As(&descriptor_2);
159 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52160 BLUETOOTH_LOG(ERROR) << "As IGattDescriptor2 failed: "
161 << logging::SystemErrorCodeToString(hr);
Sean Maher5b9af51f2022-11-21 15:32:47162 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Lei Zhang494bc8b2022-09-20 16:52:41163 FROM_HERE,
164 base::BindOnce(std::move(error_callback),
165 BluetoothGattService::GattErrorCode::kFailed));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45166 return;
167 }
168
169 ComPtr<IBuffer> buffer;
170 hr = base::win::CreateIBufferFromData(value.data(), value.size(), &buffer);
171 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52172 BLUETOOTH_LOG(ERROR) << "base::win::CreateIBufferFromData failed: "
173 << logging::SystemErrorCodeToString(hr);
Sean Maher5b9af51f2022-11-21 15:32:47174 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Lei Zhang494bc8b2022-09-20 16:52:41175 FROM_HERE,
176 base::BindOnce(std::move(error_callback),
177 BluetoothGattService::GattErrorCode::kFailed));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45178 return;
179 }
180
181 ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
182 hr = descriptor_2->WriteValueWithResultAsync(buffer.Get(), &write_value_op);
183 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52184 BLUETOOTH_LOG(ERROR) << "GattDescriptor::WriteValueWithResultAsync failed: "
185 << logging::SystemErrorCodeToString(hr);
Sean Maher5b9af51f2022-11-21 15:32:47186 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Lei Zhang494bc8b2022-09-20 16:52:41187 FROM_HERE,
188 base::BindOnce(std::move(error_callback),
189 BluetoothGattService::GattErrorCode::kFailed));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45190 return;
191 }
192
Reilly Grant4bc137c2018-12-13 22:55:15193 hr = base::win::PostAsyncResults(
Jan Wilken Dörried0a3dc62018-08-06 10:15:45194 std::move(write_value_op),
195 base::BindOnce(
196 &BluetoothRemoteGattDescriptorWinrt::OnWriteValueWithResult,
197 weak_ptr_factory_.GetWeakPtr()));
198
199 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52200 BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
201 << logging::SystemErrorCodeToString(hr);
Sean Maher5b9af51f2022-11-21 15:32:47202 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Lei Zhang494bc8b2022-09-20 16:52:41203 FROM_HERE,
204 base::BindOnce(std::move(error_callback),
205 BluetoothGattService::GattErrorCode::kFailed));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45206 return;
207 }
208
danakj056b93572019-04-23 16:04:45209 pending_write_callbacks_ = std::make_unique<PendingWriteCallbacks>(
danakjfcba225f2019-04-23 17:06:49210 std::move(callback), std::move(error_callback));
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16211}
212
Jan Wilken Dörried0a3dc62018-08-06 10:15:45213IGattDescriptor* BluetoothRemoteGattDescriptorWinrt::GetDescriptorForTesting() {
214 return descriptor_.Get();
215}
216
Jan Wilken Dörried0a3dc62018-08-06 10:15:45217BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
218 PendingWriteCallbacks(base::OnceClosure callback,
219 ErrorCallback error_callback)
220 : callback(std::move(callback)),
221 error_callback(std::move(error_callback)) {}
222
223BluetoothRemoteGattDescriptorWinrt::PendingWriteCallbacks::
224 ~PendingWriteCallbacks() = default;
225
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57226BluetoothRemoteGattDescriptorWinrt::BluetoothRemoteGattDescriptorWinrt(
227 BluetoothRemoteGattCharacteristic* characteristic,
228 Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
229 GenericAttributeProfile::IGattDescriptor>
230 descriptor,
231 BluetoothUUID uuid,
232 uint16_t attribute_handle)
233 : characteristic_(characteristic),
234 descriptor_(std::move(descriptor)),
235 uuid_(std::move(uuid)),
236 identifier_(base::StringPrintf("%s/%s_%04x",
237 characteristic_->GetIdentifier().c_str(),
238 uuid_.value().c_str(),
Jeremy Roman2b7c9502019-08-21 22:34:08239 attribute_handle)) {}
Jan Wilken Dörried0a3dc62018-08-06 10:15:45240
241void BluetoothRemoteGattDescriptorWinrt::OnReadValue(
242 ComPtr<IGattReadResult> read_result) {
Chris Mumford6627ae42021-05-03 18:54:40243 DCHECK(pending_read_callback_);
244 auto pending_read_callback = std::move(pending_read_callback_);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45245
246 if (!read_result) {
Martin Kreichgauerc8a70012020-01-31 01:08:52247 BLUETOOTH_LOG(ERROR)
248 << "GattDescriptor::ReadValueWithCacheModeAsync returned no result";
Chris Mumford6627ae42021-05-03 18:54:40249 std::move(pending_read_callback)
Lei Zhang494bc8b2022-09-20 16:52:41250 .Run(BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40251 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45252 return;
253 }
254
255 GattCommunicationStatus status;
256 HRESULT hr = read_result->get_Status(&status);
257 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52258 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
259 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40260 std::move(pending_read_callback)
Lei Zhang494bc8b2022-09-20 16:52:41261 .Run(BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40262 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45263 return;
264 }
265
266 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52267 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
Jan Wilken Dörried0a3dc62018-08-06 10:15:45268 ComPtr<IGattReadResult2> read_result_2;
269 hr = read_result.As(&read_result_2);
270 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52271 BLUETOOTH_LOG(ERROR) << "As IGattReadResult2 failed: "
272 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40273 std::move(pending_read_callback)
Lei Zhang494bc8b2022-09-20 16:52:41274 .Run(BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40275 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45276 return;
277 }
278
Chris Mumford6627ae42021-05-03 18:54:40279 std::move(pending_read_callback)
danakj056b93572019-04-23 16:04:45280 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
Chris Mumford6627ae42021-05-03 18:54:40281 read_result_2.Get()),
282 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45283 return;
284 }
285
286 ComPtr<IBuffer> value;
287 hr = read_result->get_Value(&value);
288 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52289 BLUETOOTH_LOG(ERROR) << "Getting Descriptor Value failed: "
290 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40291 std::move(pending_read_callback)
Lei Zhang494bc8b2022-09-20 16:52:41292 .Run(BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40293 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45294 return;
295 }
296
297 uint8_t* data = nullptr;
298 uint32_t length = 0;
299 hr = base::win::GetPointerToBufferData(value.Get(), &data, &length);
300 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52301 BLUETOOTH_LOG(ERROR) << "Getting Pointer To Buffer Data failed: "
302 << logging::SystemErrorCodeToString(hr);
Chris Mumford6627ae42021-05-03 18:54:40303 std::move(pending_read_callback)
Lei Zhang494bc8b2022-09-20 16:52:41304 .Run(BluetoothGattService::GattErrorCode::kFailed,
Chris Mumford6627ae42021-05-03 18:54:40305 /*value=*/std::vector<uint8_t>());
Jan Wilken Dörried0a3dc62018-08-06 10:15:45306 return;
307 }
308
309 value_.assign(data, data + length);
Arthur Sonzogni9021f6e2024-02-07 20:29:38310 std::move(pending_read_callback).Run(/*error_code=*/std::nullopt, 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) {
Martin Kreichgauerc8a70012020-01-31 01:08:52319 BLUETOOTH_LOG(ERROR)
320 << "GattDescriptor::WriteValueWithResultAsync returned no result";
danakj056b93572019-04-23 16:04:45321 std::move(pending_write_callbacks->error_callback)
Lei Zhang494bc8b2022-09-20 16:52:41322 .Run(BluetoothGattService::GattErrorCode::kFailed);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45323 return;
324 }
325
326 GattCommunicationStatus status;
327 HRESULT hr = write_result->get_Status(&status);
328 if (FAILED(hr)) {
Martin Kreichgauerc8a70012020-01-31 01:08:52329 BLUETOOTH_LOG(ERROR) << "Getting GATT Communication Status failed: "
330 << logging::SystemErrorCodeToString(hr);
danakj056b93572019-04-23 16:04:45331 std::move(pending_write_callbacks->error_callback)
Lei Zhang494bc8b2022-09-20 16:52:41332 .Run(BluetoothGattService::GattErrorCode::kFailed);
Jan Wilken Dörried0a3dc62018-08-06 10:15:45333 return;
334 }
335
336 if (status != GattCommunicationStatus_Success) {
Martin Kreichgauerc8a70012020-01-31 01:08:52337 BLUETOOTH_LOG(ERROR) << "Unexpected GattCommunicationStatus: " << status;
danakj056b93572019-04-23 16:04:45338 std::move(pending_write_callbacks->error_callback)
339 .Run(BluetoothRemoteGattServiceWinrt::GetGattErrorCode(
340 write_result.Get()));
Jan Wilken Dörried0a3dc62018-08-06 10:15:45341 return;
342 }
343
344 std::move(pending_write_callbacks->callback).Run();
345}
Jan Wilken Dörrie7dd23fd62018-08-06 09:06:57346
Jan Wilken Doerrie2a3e6c92018-07-31 08:39:16347} // namespace device