Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc

Issue 1606013002: BLE GATT service implementation in Chrome for Windows 8 and later (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update Build.gn Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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_characteristic_win.h"
6
7 #include "base/bind.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "device/bluetooth/bluetooth_gatt_notify_session_win.h"
10
11 namespace device {
12
13 void WinOnRemoteCharacteristicValueChanged(BTH_LE_GATT_EVENT_TYPE type,
14 PVOID event_parameter,
15 PVOID context) {
16 BluetoothRemoteGattCharacteristicWin* characteristic =
17 (BluetoothRemoteGattCharacteristicWin*)context;
18 characteristic->OnRemoteCharacteristicValueChanged(type, event_parameter);
19 }
20
21 void BluetoothRemoteGattCharacteristicWin::
22 NotifyCharacteristicDiscComplIfNecessary() {
23 if (descriptor_discovered_ &&
24 completed_descriptors_.size() == included_descriptor_objects_.size() &&
25 (characteristic_value_initialized_ ||
26 !characteristic_info_->IsReadable) &&
27 !complete_notified_) {
28 parent_service_->NotifyGattCharacteristicAdded(this);
29 complete_notified_ = true;
30 }
31 }
32
33 void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors(
34 PBTH_LE_GATT_DESCRIPTOR descriptors,
35 uint16_t num) {
36 if (num == 0) {
37 completed_descriptors_.clear();
38 included_descriptor_objects_.clear();
39 return;
40 }
41 // Map of retrieved descriptor uuid value to its index in |descriptors|.
42 std::map<std::string, uint16_t> current_descriptors;
43 for (uint16_t i = 0; i < num; i++) {
44 current_descriptors[task_manager_->BluetoothLowEnergyUuidToBluetoothUuid(
45 descriptors[i].DescriptorUuid)
46 .value()] = i;
47 }
48 // Map of known descriptor uuid value to its identifier.
49 std::map<std::string, std::string> known_descriptors;
50 if (included_descriptor_objects_.size() != 0) {
51 for (auto e : included_descriptor_objects_) {
52 known_descriptors[e.second->GetUUID().value()] = e.first;
53 }
54 std::vector<std::string> removed_descriptors;
55 for (auto e : known_descriptors) {
56 if (current_descriptors.find(e.first) == current_descriptors.end()) {
57 removed_descriptors.push_back(e.second);
58 }
59 }
60 for (auto e : removed_descriptors) {
61 completed_descriptors_.erase(e);
62 included_descriptor_objects_.erase(e);
63 }
64 // Update previously known descriptors.
65 for (auto e : included_descriptor_objects_)
66 e.second->Update();
67 }
68
69 // Return if no new descriptors have been added.
70 if (included_descriptor_objects_.size() == num)
71 return;
72
73 // Add new descriptors.
74 for (auto e : current_descriptors) {
75 if (known_descriptors.find(e.first) == known_descriptors.end()) {
76 PBTH_LE_GATT_DESCRIPTOR win_descriptor_info =
77 new BTH_LE_GATT_DESCRIPTOR();
78 *win_descriptor_info = descriptors[e.second];
79 BluetoothRemoteGattDescriptorWin* descriptor_object =
80 new BluetoothRemoteGattDescriptorWin(
81 adapter_, parent_service_->GetServicePath(), this,
82 win_descriptor_info, ui_task_runner_);
83 included_descriptor_objects_.add(
84 descriptor_object->GetIdentifier(),
85 scoped_ptr<BluetoothRemoteGattDescriptorWin>(descriptor_object));
86 }
87 }
88 }
89
90 void BluetoothRemoteGattCharacteristicWin::GetIncludedDescriptorsCallback(
91 PBTH_LE_GATT_DESCRIPTOR descriptors,
92 uint16_t num,
93 HRESULT hr) {
94 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
95 if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
96 return;
97 descriptor_discovered_ = true;
98 UpdateIncludedDescriptors(descriptors, num);
99 NotifyCharacteristicDiscComplIfNecessary();
100 }
101
102 // Called by included descriptors.
103 void BluetoothRemoteGattCharacteristicWin::NotifyGattDescriptorAdded(
104 BluetoothRemoteGattDescriptorWin* descriptor) {
105 completed_descriptors_.insert(descriptor->GetIdentifier());
106 adapter_->NotifyGattDescriptorAdded(descriptor);
107 NotifyCharacteristicDiscComplIfNecessary();
108 }
109
110 void BluetoothRemoteGattCharacteristicWin::NotifyGattCharacteristicValueChanged(
111 uint8_t* new_value,
112 ULONG size) {
113 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
114 characteristic_value_.clear();
115 for (ULONG i = 0; i < size; i++)
116 characteristic_value_.push_back(new_value[i]);
117 adapter_->NotifyGattCharacteristicValueChanged(this, characteristic_value_);
118 }
119
120 void BluetoothRemoteGattCharacteristicWin::OnRemoteCharacteristicValueChanged(
121 BTH_LE_GATT_EVENT_TYPE type,
122 PVOID event_parameter) {
123 if (type == CharacteristicValueChangedEvent) {
124 BLUETOOTH_GATT_VALUE_CHANGED_EVENT* event =
125 (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)event_parameter;
126 PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value_win =
127 event->CharacteristicValue;
128
129 uint8_t* new_value = new uint8_t[new_value_win->DataSize];
130 memcpy(new_value, &(new_value_win->Data[0]), new_value_win->DataSize);
131 ui_task_runner_->PostTask(
132 FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristicWin::
133 NotifyGattCharacteristicValueChanged,
134 weak_ptr_factory_.GetWeakPtr(),
135 base::Owned(new_value), new_value_win->DataSize));
136 }
137 }
138
139 void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
140 BLUETOOTH_GATT_EVENT_HANDLE event_handle,
141 HRESULT hr) {
142 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
143 if (FAILED(hr)) {
144 for (auto callback : start_notifying_callback_)
145 callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
146 start_notifying_callback_.clear();
147 return;
148 }
149
150 for (auto callback : start_notifying_callback_) {
151 scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
152 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
153 callback.first.Run(std::move(notify_session));
154 number_of_active_notify_sessions_++;
155 }
156 start_notifying_callback_.clear();
157 registered_event_handle_ = event_handle;
158 is_notifying_ = true;
159 }
160
161 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
162 BluetoothRemoteGattServiceWin* parent_service,
163 BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
164 scoped_refptr<base::SequencedTaskRunner>& ui_task_runner)
165 : parent_service_(parent_service),
166 characteristic_info_(characteristic_info),
167 ui_task_runner_(ui_task_runner),
168 characteristic_value_initialized_(false),
169 registered_event_handle_(NULL),
170 weak_ptr_factory_(this),
171 complete_notified_(false),
172 is_notifying_(false),
173 number_of_active_notify_sessions_(0) {
174 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
175 characteristic_value_.clear();
176 included_descriptor_objects_.clear();
177 completed_descriptors_.clear();
178 read_remote_characteristic_value_callbacks_.clear();
179 write_remote_characteristic_value_callback_.clear();
180 start_notifying_callback_.clear();
181
182 adapter_ = parent_service_->GetAdapter();
183 task_manager_ = adapter_->GetWinBluetoothTaskManager();
184 DCHECK(parent_service_);
185 DCHECK(characteristic_info_);
186 DCHECK(adapter_);
187 DCHECK(task_manager_);
188
189 characteristic_uuid_ = task_manager_->BluetoothLowEnergyUuidToBluetoothUuid(
190 characteristic_info_->CharacteristicUuid);
191 Update();
192 }
193
194 BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() {
195 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
196 if (registered_event_handle_ != NULL) {
197 task_manager_->UnregisterCharacteristicValueChangedEvent(
198 registered_event_handle_);
199 }
200
201 completed_descriptors_.clear();
202 included_descriptor_objects_.clear();
203 adapter_->NotifyGattCharacteristicRemoved(this);
204 }
205
206 std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const {
207 return parent_service_->GetIdentifier() + "_" + characteristic_uuid_.value();
208 }
209
210 BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const {
211 return characteristic_uuid_;
212 }
213
214 bool BluetoothRemoteGattCharacteristicWin::IsLocal() const {
215 return false;
216 }
217
218 std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
219 return const_cast<std::vector<uint8_t>&>(characteristic_value_);
220 }
221
222 BluetoothGattService* BluetoothRemoteGattCharacteristicWin::GetService() const {
223 return parent_service_;
224 }
225
226 BluetoothGattCharacteristic::Properties
227 BluetoothRemoteGattCharacteristicWin::GetProperties() const {
228 BluetoothGattCharacteristic::Properties properties = PROPERTY_NONE;
229
230 if (characteristic_info_.get()->IsBroadcastable)
231 properties = properties | PROPERTY_BROADCAST;
232 if (characteristic_info_.get()->IsReadable)
233 properties = properties | PROPERTY_READ;
234 if (characteristic_info_.get()->IsWritableWithoutResponse)
235 properties = properties | PROPERTY_WRITE_WITHOUT_RESPONSE;
236 if (characteristic_info_.get()->IsWritable)
237 properties = properties | PROPERTY_WRITE;
238 if (characteristic_info_.get()->IsNotifiable)
239 properties = properties | PROPERTY_NOTIFY;
240 if (characteristic_info_.get()->IsIndicatable)
241 properties = properties | PROPERTY_INDICATE;
242 if (characteristic_info_.get()->IsSignedWritable)
243 properties = properties | PROPERTY_AUTHENTICATED_SIGNED_WRITES;
244 if (characteristic_info_.get()->HasExtendedProperties)
245 properties = properties | PROPERTY_EXTENDED_PROPERTIES;
246
247 return properties;
248 }
249
250 BluetoothGattCharacteristic::Permissions
251 BluetoothRemoteGattCharacteristicWin::GetPermissions() const {
252 BluetoothGattCharacteristic::Permissions permissions = PERMISSION_NONE;
253
254 if (characteristic_info_.get()->IsReadable)
255 permissions = permissions | PERMISSION_READ;
256 if (characteristic_info_.get()->IsWritable)
257 permissions = permissions | PERMISSION_WRITE;
258
259 return permissions;
260 }
261
262 bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const {
263 return is_notifying_;
264 }
265
266 std::vector<BluetoothGattDescriptor*>
267 BluetoothRemoteGattCharacteristicWin::GetDescriptors() const {
268 std::vector<BluetoothGattDescriptor*> descriptors;
269 for (auto descriptor : included_descriptor_objects_)
270 descriptors.push_back(descriptor.second);
271 return descriptors;
272 }
273
274 BluetoothGattDescriptor* BluetoothRemoteGattCharacteristicWin::GetDescriptor(
275 const std::string& identifier) const {
276 GattDescriptorMap::const_iterator it =
277 included_descriptor_objects_.find(identifier);
278 if (it != included_descriptor_objects_.end())
279 return it->second;
280 return nullptr;
281 }
282
283 bool BluetoothRemoteGattCharacteristicWin::AddDescriptor(
284 BluetoothGattDescriptor* descriptor) {
285 NOTIMPLEMENTED();
286 return false;
287 }
288
289 bool BluetoothRemoteGattCharacteristicWin::UpdateValue(
290 const std::vector<uint8_t>& value) {
291 NOTIMPLEMENTED();
292 return false;
293 }
294
295 void BluetoothRemoteGattCharacteristicWin::StartNotifySession(
296 const NotifySessionCallback& callback,
297 const ErrorCallback& error_callback) {
298 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
299 if (is_notifying_) {
300 scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
301 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
302 callback.Run(std::move(notify_session));
303 number_of_active_notify_sessions_++;
304 return;
305 }
306
307 if (characteristic_info_->IsNotifiable ||
308 characteristic_info_->IsIndicatable) {
309 start_notifying_callback_.push_back(
310 std::make_pair(callback, error_callback));
311 task_manager_->PostRegisterCharacteristicValueChangedEvent(
312 parent_service_->GetServicePath(), characteristic_info_.get(),
313 base::Bind(&BluetoothRemoteGattCharacteristicWin::
314 GattEventRegistrationCallback,
315 weak_ptr_factory_.GetWeakPtr()),
316 &WinOnRemoteCharacteristicValueChanged, (PVOID) this);
317 } else {
318 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED);
319 }
320 }
321
322 void BluetoothRemoteGattCharacteristicWin::StopNotifySession() {
323 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
324 if (!is_notifying_)
325 return;
326
327 number_of_active_notify_sessions_--;
328 if (number_of_active_notify_sessions_ > 0)
329 return;
330 task_manager_->UnregisterCharacteristicValueChangedEvent(
331 registered_event_handle_);
332 registered_event_handle_ = NULL;
333 is_notifying_ = false;
334 number_of_active_notify_sessions_ = 0;
335 start_notifying_callback_.clear();
336 }
337
338 void BluetoothRemoteGattCharacteristicWin::ReadCharacteristicValueCallback(
339 PBTH_LE_GATT_CHARACTERISTIC_VALUE value,
340 HRESULT hr) {
341 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
342 if (FAILED(hr)) {
343 LOG(ERROR) << "Failed at reading characteristic value with error ";
344 for (const auto callback : read_remote_characteristic_value_callbacks_)
345 callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
346 } else {
347 characteristic_value_.clear();
348 for (ULONG i = 0; i < value->DataSize; i++)
349 characteristic_value_.push_back(value->Data[i]);
350 for (const auto callback : read_remote_characteristic_value_callbacks_)
351 callback.first.Run(characteristic_value_);
352 }
353
354 if (!characteristic_value_initialized_) {
355 characteristic_value_initialized_ = true;
356 NotifyCharacteristicDiscComplIfNecessary();
357 }
358 read_remote_characteristic_value_callbacks_.clear();
359 }
360
361 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
362 const ValueCallback& callback,
363 const ErrorCallback& error_callback) {
364 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
365 if (!characteristic_info_.get()->IsReadable)
366 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
367
368 read_remote_characteristic_value_callbacks_.push_back(
369 std::make_pair(callback, error_callback));
370 task_manager_->PostReadCharacteristicValue(
371 parent_service_->GetServicePath(), characteristic_info_.get(),
372 base::Bind(&BluetoothRemoteGattCharacteristicWin::
373 ReadCharacteristicValueCallback,
374 weak_ptr_factory_.GetWeakPtr()));
375 }
376
377 void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristicCallback(
378 HRESULT hr) {
379 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
380 if (FAILED(hr)) {
381 for (const auto callback : write_remote_characteristic_value_callback_)
382 callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
383 } else {
384 for (const auto callback : write_remote_characteristic_value_callback_)
385 callback.first.Run();
386 }
387 write_remote_characteristic_value_callback_.clear();
388 }
389
390 void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
391 const std::vector<uint8_t>& new_value,
392 const base::Closure& callback,
393 const ErrorCallback& error_callback) {
394 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
395 if (!characteristic_info_.get()->IsWritable)
396 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
397
398 write_remote_characteristic_value_callback_.push_back(
399 std::make_pair(callback, error_callback));
400 task_manager_->PostWriteCharacteristicValue(
401 parent_service_->GetServicePath(), characteristic_info_.get(), new_value,
402 base::Bind(&BluetoothRemoteGattCharacteristicWin::
403 WriteRemoteCharacteristicCallback,
404 weak_ptr_factory_.GetWeakPtr()));
405 }
406
407 void BluetoothRemoteGattCharacteristicWin::Update() {
408 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
409 task_manager_->PostGetGattIncludedDescriptors(
410 parent_service_->GetServicePath(), characteristic_info_.get(),
411 base::Bind(
412 &BluetoothRemoteGattCharacteristicWin::GetIncludedDescriptorsCallback,
413 weak_ptr_factory_.GetWeakPtr()));
414
415 if (characteristic_info_->IsReadable) {
416 task_manager_->PostReadCharacteristicValue(
417 parent_service_->GetServicePath(), characteristic_info_.get(),
418 base::Bind(&BluetoothRemoteGattCharacteristicWin::
419 ReadCharacteristicValueCallback,
420 weak_ptr_factory_.GetWeakPtr()));
421 }
422 }
423
424 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698