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

Side by Side Diff: device/bluetooth/bluetooth_low_energy_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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/bluetooth/bluetooth_low_energy_win.h" 5 #include "device/bluetooth/bluetooth_low_energy_win.h"
6 6
7 #include "base/files/file.h" 7 #include "base/files/file.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 bool StringToBluetoothAddress(const std::string& value, 56 bool StringToBluetoothAddress(const std::string& value,
57 BLUETOOTH_ADDRESS* btha, 57 BLUETOOTH_ADDRESS* btha,
58 std::string* error) { 58 std::string* error) {
59 if (value.length() != 6 * 2) { 59 if (value.length() != 6 * 2) {
60 *error = kInvalidBluetoothAddress; 60 *error = kInvalidBluetoothAddress;
61 return false; 61 return false;
62 } 62 }
63 63
64 int buffer[6]; 64 int buffer[6];
65 int result = sscanf_s(value.c_str(), 65 int result =
66 "%02X%02X%02X%02X%02X%02X", 66 sscanf_s(value.c_str(), "%02X%02X%02X%02X%02X%02X", &buffer[5],
67 &buffer[5], 67 &buffer[4], &buffer[3], &buffer[2], &buffer[1], &buffer[0]);
68 &buffer[4],
69 &buffer[3],
70 &buffer[2],
71 &buffer[1],
72 &buffer[0]);
73 if (result != 6) { 68 if (result != 6) {
74 *error = kInvalidBluetoothAddress; 69 *error = kInvalidBluetoothAddress;
75 return false; 70 return false;
76 } 71 }
77 72
78 ZeroMemory(btha, sizeof(*btha)); 73 ZeroMemory(btha, sizeof(*btha));
79 btha->rgBytes[0] = buffer[0]; 74 btha->rgBytes[0] = buffer[0];
80 btha->rgBytes[1] = buffer[1]; 75 btha->rgBytes[1] = buffer[1];
81 btha->rgBytes[2] = buffer[2]; 76 btha->rgBytes[2] = buffer[2];
82 btha->rgBytes[3] = buffer[3]; 77 btha->rgBytes[3] = buffer[3];
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 } 160 }
166 161
167 bool CollectBluetoothLowEnergyDeviceProperty( 162 bool CollectBluetoothLowEnergyDeviceProperty(
168 const ScopedDeviceInfoSetHandle& device_info_handle, 163 const ScopedDeviceInfoSetHandle& device_info_handle,
169 PSP_DEVINFO_DATA device_info_data, 164 PSP_DEVINFO_DATA device_info_data,
170 const DEVPROPKEY& key, 165 const DEVPROPKEY& key,
171 scoped_ptr<DevicePropertyValue>* value, 166 scoped_ptr<DevicePropertyValue>* value,
172 std::string* error) { 167 std::string* error) {
173 DWORD required_length; 168 DWORD required_length;
174 DEVPROPTYPE prop_type; 169 DEVPROPTYPE prop_type;
175 BOOL success = SetupDiGetDeviceProperty(device_info_handle.Get(), 170 BOOL success =
176 device_info_data, 171 SetupDiGetDeviceProperty(device_info_handle.Get(), device_info_data, &key,
177 &key, 172 &prop_type, NULL, 0, &required_length, 0);
178 &prop_type,
179 NULL,
180 0,
181 &required_length,
182 0);
183 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) 173 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
184 return false; 174 return false;
185 175
186 scoped_ptr<uint8_t[]> prop_value(new uint8_t[required_length]); 176 scoped_ptr<uint8_t[]> prop_value(new uint8_t[required_length]);
187 DWORD actual_length = required_length; 177 DWORD actual_length = required_length;
188 success = SetupDiGetDeviceProperty(device_info_handle.Get(), 178 success = SetupDiGetDeviceProperty(device_info_handle.Get(), device_info_data,
189 device_info_data, 179 &key, &prop_type, prop_value.get(),
190 &key, 180 actual_length, &required_length, 0);
191 &prop_type,
192 prop_value.get(),
193 actual_length,
194 &required_length,
195 0);
196 if (!CheckSuccess(!!success, kDeviceInfoError, error)) 181 if (!CheckSuccess(!!success, kDeviceInfoError, error))
197 return false; 182 return false;
198 if (!CheckExpectedLength( 183 if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError,
199 actual_length, required_length, kDeviceInfoError, error)) { 184 error)) {
200 return false; 185 return false;
201 } 186 }
202 187
203 (*value) = scoped_ptr<DevicePropertyValue>( 188 (*value) = scoped_ptr<DevicePropertyValue>(
204 new DevicePropertyValue(prop_type, prop_value.Pass(), actual_length)); 189 new DevicePropertyValue(prop_type, std::move(prop_value), actual_length));
205 return true; 190 return true;
206 } 191 }
207 192
208 bool CollectBluetoothLowEnergyDeviceRegistryProperty( 193 bool CollectBluetoothLowEnergyDeviceRegistryProperty(
209 const ScopedDeviceInfoSetHandle& device_info_handle, 194 const ScopedDeviceInfoSetHandle& device_info_handle,
210 PSP_DEVINFO_DATA device_info_data, 195 PSP_DEVINFO_DATA device_info_data,
211 DWORD property_id, 196 DWORD property_id,
212 scoped_ptr<DeviceRegistryPropertyValue>* value, 197 scoped_ptr<DeviceRegistryPropertyValue>* value,
213 std::string* error) { 198 std::string* error) {
214 ULONG required_length = 0; 199 ULONG required_length = 0;
215 BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(), 200 BOOL success = SetupDiGetDeviceRegistryProperty(
216 device_info_data, 201 device_info_handle.Get(), device_info_data, property_id, NULL, NULL, 0,
217 property_id, 202 &required_length);
218 NULL,
219 NULL,
220 0,
221 &required_length);
222 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) 203 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
223 return false; 204 return false;
224 205
225 scoped_ptr<uint8_t[]> property_value(new uint8_t[required_length]); 206 scoped_ptr<uint8_t[]> property_value(new uint8_t[required_length]);
226 ULONG actual_length = required_length; 207 ULONG actual_length = required_length;
227 DWORD property_type; 208 DWORD property_type;
228 success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(), 209 success = SetupDiGetDeviceRegistryProperty(
229 device_info_data, 210 device_info_handle.Get(), device_info_data, property_id, &property_type,
230 property_id, 211 property_value.get(), actual_length, &required_length);
231 &property_type,
232 property_value.get(),
233 actual_length,
234 &required_length);
235 if (!CheckSuccess(!!success, kDeviceInfoError, error)) 212 if (!CheckSuccess(!!success, kDeviceInfoError, error))
236 return false; 213 return false;
237 if (!CheckExpectedLength( 214 if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError,
238 actual_length, required_length, kDeviceInfoError, error)) { 215 error)) {
239 return false; 216 return false;
240 } 217 }
241 218
242 (*value) = DeviceRegistryPropertyValue::Create( 219 (*value) = DeviceRegistryPropertyValue::Create(
243 property_type, property_value.Pass(), actual_length).Pass(); 220 property_type, std::move(property_value), actual_length)
221 .Pass();
244 return true; 222 return true;
245 } 223 }
246 224
247 bool CollectBluetoothLowEnergyDeviceInstanceId( 225 bool CollectBluetoothLowEnergyDeviceInstanceId(
248 const ScopedDeviceInfoSetHandle& device_info_handle, 226 const ScopedDeviceInfoSetHandle& device_info_handle,
249 PSP_DEVINFO_DATA device_info_data, 227 PSP_DEVINFO_DATA device_info_data,
250 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info, 228 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
251 std::string* error) { 229 std::string* error) {
252 ULONG required_length = 0; 230 ULONG required_length = 0;
253 BOOL success = SetupDiGetDeviceInstanceId( 231 BOOL success = SetupDiGetDeviceInstanceId(
254 device_info_handle.Get(), device_info_data, NULL, 0, &required_length); 232 device_info_handle.Get(), device_info_data, NULL, 0, &required_length);
255 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) 233 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
256 return false; 234 return false;
257 235
258 scoped_ptr<WCHAR[]> instance_id(new WCHAR[required_length]); 236 scoped_ptr<WCHAR[]> instance_id(new WCHAR[required_length]);
259 ULONG actual_length = required_length; 237 ULONG actual_length = required_length;
260 success = SetupDiGetDeviceInstanceId(device_info_handle.Get(), 238 success = SetupDiGetDeviceInstanceId(device_info_handle.Get(),
261 device_info_data, 239 device_info_data, instance_id.get(),
262 instance_id.get(), 240 actual_length, &required_length);
263 actual_length,
264 &required_length);
265 if (!CheckSuccess(!!success, kDeviceInfoError, error)) 241 if (!CheckSuccess(!!success, kDeviceInfoError, error))
266 return false; 242 return false;
267 if (!CheckExpectedLength( 243 if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError,
268 actual_length, required_length, kDeviceInfoError, error)) { 244 error)) {
269 return false; 245 return false;
270 } 246 }
271 247
272 if (actual_length >= 1) { 248 if (actual_length >= 1) {
273 // Ensure string is zero terminated. 249 // Ensure string is zero terminated.
274 instance_id.get()[actual_length - 1] = 0; 250 instance_id.get()[actual_length - 1] = 0;
275 device_info->id = base::SysWideToUTF8(instance_id.get()); 251 device_info->id = base::SysWideToUTF8(instance_id.get());
276 } 252 }
277 return true; 253 return true;
278 } 254 }
279 255
280 bool CollectBluetoothLowEnergyDeviceFriendlyName( 256 bool CollectBluetoothLowEnergyDeviceFriendlyName(
281 const ScopedDeviceInfoSetHandle& device_info_handle, 257 const ScopedDeviceInfoSetHandle& device_info_handle,
282 PSP_DEVINFO_DATA device_info_data, 258 PSP_DEVINFO_DATA device_info_data,
283 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info, 259 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
284 std::string* error) { 260 std::string* error) {
285 scoped_ptr<DeviceRegistryPropertyValue> property_value; 261 scoped_ptr<DeviceRegistryPropertyValue> property_value;
286 if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle, 262 if (!CollectBluetoothLowEnergyDeviceRegistryProperty(
287 device_info_data, 263 device_info_handle, device_info_data, SPDRP_FRIENDLYNAME,
288 SPDRP_FRIENDLYNAME, 264 &property_value, error)) {
289 &property_value,
290 error)) {
291 return false; 265 return false;
292 } 266 }
293 267
294 if (property_value->property_type() != REG_SZ) { 268 if (property_value->property_type() != REG_SZ) {
295 *error = kDeviceFriendlyNameError; 269 *error = kDeviceFriendlyNameError;
296 return false; 270 return false;
297 } 271 }
298 272
299 device_info->friendly_name = property_value->AsString(); 273 device_info->friendly_name = property_value->AsString();
300 return true; 274 return true;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 return ExtractBluetoothAddressFromDeviceInstanceId( 309 return ExtractBluetoothAddressFromDeviceInstanceId(
336 device_info->id, &device_info->address, error); 310 device_info->id, &device_info->address, error);
337 } 311 }
338 312
339 bool CollectBluetoothLowEnergyDeviceStatus( 313 bool CollectBluetoothLowEnergyDeviceStatus(
340 const ScopedDeviceInfoSetHandle& device_info_handle, 314 const ScopedDeviceInfoSetHandle& device_info_handle,
341 PSP_DEVINFO_DATA device_info_data, 315 PSP_DEVINFO_DATA device_info_data,
342 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info, 316 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
343 std::string* error) { 317 std::string* error) {
344 scoped_ptr<DevicePropertyValue> value; 318 scoped_ptr<DevicePropertyValue> value;
345 if (!CollectBluetoothLowEnergyDeviceProperty(device_info_handle, 319 if (!CollectBluetoothLowEnergyDeviceProperty(
346 device_info_data, 320 device_info_handle, device_info_data, DEVPKEY_Device_DevNodeStatus,
347 DEVPKEY_Device_DevNodeStatus, 321 &value, error)) {
348 &value,
349 error)) {
350 return false; 322 return false;
351 } 323 }
352 324
353 if (value->property_type() != DEVPROP_TYPE_UINT32) { 325 if (value->property_type() != DEVPROP_TYPE_UINT32) {
354 *error = kDeviceInfoError; 326 *error = kDeviceInfoError;
355 return false; 327 return false;
356 } 328 }
357 329
358 device_info->connected = !(value->AsUint32() & DN_DEVICE_DISCONNECTED); 330 device_info->connected = !(value->AsUint32() & DN_DEVICE_DISCONNECTED);
359 // Windows 8 exposes BLE devices only if they are visible and paired. This 331 // Windows 8 exposes BLE devices only if they are visible and paired. This
360 // might change in the future if Windows offers a public API for discovering 332 // might change in the future if Windows offers a public API for discovering
361 // and pairing BLE devices. 333 // and pairing BLE devices.
362 device_info->visible = true; 334 device_info->visible = true;
363 device_info->authenticated = true; 335 device_info->authenticated = true;
364 return true; 336 return true;
365 } 337 }
366 338
367 bool CollectBluetoothLowEnergyDeviceServices( 339 bool CollectBluetoothLowEnergyDeviceServices(
368 const base::FilePath& device_path, 340 const base::FilePath& device_path,
369 ScopedVector<BluetoothLowEnergyServiceInfo>* services, 341 ScopedVector<BluetoothLowEnergyServiceInfo>* services,
370 std::string* error) { 342 std::string* error) {
371 base::File file(device_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 343 base::File file(device_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
372 if (!file.IsValid()) { 344 if (!file.IsValid()) {
373 *error = file.ErrorToString(file.error_details()); 345 *error = file.ErrorToString(file.error_details());
374 return false; 346 return false;
375 } 347 }
376 348
377 USHORT required_length; 349 BTH_LE_GATT_SERVICE* primary_services;
378 HRESULT hr = BluetoothGATTGetServices(file.GetPlatformFile(), 350 USHORT counts;
379 0, 351 HRESULT hr = device::win::ReadPrimaryServicesOfADevice(
380 NULL, 352 file.GetPlatformFile(), &primary_services, &counts);
381 &required_length, 353 if (!CheckHResult(hr, kDeviceInfoError, error))
382 BLUETOOTH_GATT_FLAG_NONE);
383 if (CheckNoData(hr, required_length))
384 return true;
385 if (!CheckMoreData(hr, kDeviceInfoError, error))
386 return false; 354 return false;
387 355
388 scoped_ptr<BTH_LE_GATT_SERVICE[]> gatt_services( 356 for (USHORT i = 0; i < counts; ++i) {
389 new BTH_LE_GATT_SERVICE[required_length]);
390 USHORT actual_length = required_length;
391 hr = BluetoothGATTGetServices(file.GetPlatformFile(),
392 actual_length,
393 gatt_services.get(),
394 &required_length,
395 BLUETOOTH_GATT_FLAG_NONE);
396 if (!CheckHResult(hr, kDeviceInfoError, error))
397 return false;
398 if (!CheckExpectedLength(
399 actual_length, required_length, kDeviceInfoError, error)) {
400 return false;
401 }
402
403 for (USHORT i = 0; i < actual_length; ++i) {
404 BTH_LE_GATT_SERVICE& gatt_service(gatt_services.get()[i]);
405 BluetoothLowEnergyServiceInfo* service_info = 357 BluetoothLowEnergyServiceInfo* service_info =
406 new BluetoothLowEnergyServiceInfo(); 358 new BluetoothLowEnergyServiceInfo();
407 service_info->uuid = gatt_service.ServiceUuid; 359 service_info->uuid = primary_services[i].ServiceUuid;
360 service_info->attribute_handle = primary_services[i].AttributeHandle;
408 services->push_back(service_info); 361 services->push_back(service_info);
409 } 362 }
410 363 delete primary_services;
411 return true; 364 return true;
412 } 365 }
413 366
414 bool CollectBluetoothLowEnergyDeviceInfo( 367 bool CollectBluetoothLowEnergyDeviceInfo(
415 const ScopedDeviceInfoSetHandle& device_info_handle, 368 const ScopedDeviceInfoSetHandle& device_info_handle,
416 PSP_DEVICE_INTERFACE_DATA device_interface_data, 369 PSP_DEVICE_INTERFACE_DATA device_interface_data,
417 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info, 370 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
418 std::string* error) { 371 std::string* error) {
419 // Retrieve required # of bytes for interface details 372 // Retrieve required # of bytes for interface details
420 ULONG required_length = 0; 373 ULONG required_length = 0;
421 BOOL success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(), 374 BOOL success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(),
422 device_interface_data, 375 device_interface_data, NULL, 0,
423 NULL, 376 &required_length, NULL);
424 0,
425 &required_length,
426 NULL);
427 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) 377 if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
428 return false; 378 return false;
429 379
430 scoped_ptr<uint8_t[]> interface_data(new uint8_t[required_length]); 380 scoped_ptr<uint8_t[]> interface_data(new uint8_t[required_length]);
431 ZeroMemory(interface_data.get(), required_length); 381 ZeroMemory(interface_data.get(), required_length);
432 382
433 PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data = 383 PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data =
434 reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(interface_data.get()); 384 reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(interface_data.get());
435 device_interface_detail_data->cbSize = 385 device_interface_detail_data->cbSize =
436 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 386 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
437 387
438 SP_DEVINFO_DATA device_info_data = {0}; 388 SP_DEVINFO_DATA device_info_data = {0};
439 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); 389 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
440 390
441 ULONG actual_length = required_length; 391 ULONG actual_length = required_length;
442 success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(), 392 success = SetupDiGetDeviceInterfaceDetail(
443 device_interface_data, 393 device_info_handle.Get(), device_interface_data,
444 device_interface_detail_data, 394 device_interface_detail_data, actual_length, &required_length,
445 actual_length, 395 &device_info_data);
446 &required_length,
447 &device_info_data);
448 if (!CheckSuccess(!!success, kDeviceInfoError, error)) 396 if (!CheckSuccess(!!success, kDeviceInfoError, error))
449 return false; 397 return false;
450 if (!CheckExpectedLength( 398 if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError,
451 actual_length, required_length, kDeviceInfoError, error)) { 399 error)) {
452 return false; 400 return false;
453 } 401 }
454 402
455 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo> result( 403 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo> result(
456 new device::win::BluetoothLowEnergyDeviceInfo()); 404 new device::win::BluetoothLowEnergyDeviceInfo());
457 result->path = 405 result->path =
458 base::FilePath(std::wstring(device_interface_detail_data->DevicePath)); 406 base::FilePath(std::wstring(device_interface_detail_data->DevicePath));
459 if (!CollectBluetoothLowEnergyDeviceInstanceId( 407 if (!CollectBluetoothLowEnergyDeviceInstanceId(
460 device_info_handle, &device_info_data, result, error)) { 408 device_info_handle, &device_info_data, result, error)) {
461 return false; 409 return false;
462 } 410 }
463 if (!CollectBluetoothLowEnergyDeviceFriendlyName( 411 if (!CollectBluetoothLowEnergyDeviceFriendlyName(
464 device_info_handle, &device_info_data, result, error)) { 412 device_info_handle, &device_info_data, result, error)) {
465 return false; 413 if (device_info_data.ClassGuid == GUID_BLUETOOTHLE_DEVICE_INTERFACE)
414 return false;
466 } 415 }
467 if (!CollectBluetoothLowEnergyDeviceAddress( 416 if (!CollectBluetoothLowEnergyDeviceAddress(
468 device_info_handle, &device_info_data, result, error)) { 417 device_info_handle, &device_info_data, result, error)) {
469 return false; 418 return false;
470 } 419 }
471 if (!CollectBluetoothLowEnergyDeviceStatus( 420 if (!CollectBluetoothLowEnergyDeviceStatus(
472 device_info_handle, &device_info_data, result, error)) { 421 device_info_handle, &device_info_data, result, error)) {
473 return false; 422 return false;
474 } 423 }
475 (*device_info) = result.Pass(); 424 (*device_info) = result.Pass();
476 return true; 425 return true;
477 } 426 }
478 427
479 enum DeviceInfoResult { kOk, kError, kNoMoreDevices }; 428 enum DeviceInfoResult { kOk, kError, kNoMoreDevices };
480 429
481 DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice( 430 DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
431 GUID guid,
482 const ScopedDeviceInfoSetHandle& device_info_handle, 432 const ScopedDeviceInfoSetHandle& device_info_handle,
483 DWORD device_index, 433 DWORD device_index,
484 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info, 434 scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
485 std::string* error) { 435 std::string* error) {
486 // Enumerate device of BLUETOOTHLE_DEVICE interface class 436 GUID BluetoothInterfaceGUID = guid;
487 GUID BluetoothInterfaceGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
488 SP_DEVICE_INTERFACE_DATA device_interface_data = {0}; 437 SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
489 device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 438 device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
490 BOOL success = ::SetupDiEnumDeviceInterfaces(device_info_handle.Get(), 439 BOOL success = ::SetupDiEnumDeviceInterfaces(
491 NULL, 440 device_info_handle.Get(), NULL, &BluetoothInterfaceGUID, device_index,
492 &BluetoothInterfaceGUID, 441 &device_interface_data);
493 device_index,
494 &device_interface_data);
495 if (!success) { 442 if (!success) {
496 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 443 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
497 if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) { 444 if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) {
498 return kNoMoreDevices; 445 return kNoMoreDevices;
499 } 446 }
500 *error = FormatBluetoothError(kDeviceInfoError, hr); 447 *error = FormatBluetoothError(kDeviceInfoError, hr);
501 return kError; 448 return kError;
502 } 449 }
503 450
504 if (!CollectBluetoothLowEnergyDeviceInfo( 451 if (!CollectBluetoothLowEnergyDeviceInfo(
505 device_info_handle, &device_interface_data, device_info, error)) { 452 device_info_handle, &device_interface_data, device_info, error)) {
506 return kError; 453 return kError;
507 } 454 }
508 455
509 return kOk; 456 return kOk;
510 } 457 }
511 458
512 // Opens a Device Info Set that can be used to enumerate Bluetooth LE devices 459 // Opens a Device Info Set that can be used to enumerate Bluetooth LE or Gatt
513 // present on the machine. 460 // Service devices present on the machine.
514 HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle) { 461 HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle,
515 GUID BluetoothClassGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE; 462 GUID guid) {
463 GUID BluetoothClassGUID = guid;
516 ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs( 464 ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs(
517 &BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); 465 &BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
518 if (!result.IsValid()) { 466 if (!result.IsValid()) {
519 return HRESULT_FROM_WIN32(::GetLastError()); 467 return HRESULT_FROM_WIN32(::GetLastError());
520 } 468 }
521 469
522 (*handle) = result.Pass(); 470 (*handle) = result.Pass();
523 return S_OK; 471 return S_OK;
524 } 472 }
525 473
(...skipping 25 matching lines...) Expand all
551 return scoped_ptr<DeviceRegistryPropertyValue>( 499 return scoped_ptr<DeviceRegistryPropertyValue>(
552 new DeviceRegistryPropertyValue(property_type, value.Pass(), value_size)); 500 new DeviceRegistryPropertyValue(property_type, value.Pass(), value_size));
553 } 501 }
554 502
555 DeviceRegistryPropertyValue::DeviceRegistryPropertyValue( 503 DeviceRegistryPropertyValue::DeviceRegistryPropertyValue(
556 DWORD property_type, 504 DWORD property_type,
557 scoped_ptr<uint8_t[]> value, 505 scoped_ptr<uint8_t[]> value,
558 size_t value_size) 506 size_t value_size)
559 : property_type_(property_type), 507 : property_type_(property_type),
560 value_(value.Pass()), 508 value_(value.Pass()),
561 value_size_(value_size) { 509 value_size_(value_size) {}
562 }
563 510
564 DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() { 511 DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() {}
565 }
566 512
567 std::string DeviceRegistryPropertyValue::AsString() const { 513 std::string DeviceRegistryPropertyValue::AsString() const {
568 CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ)); 514 CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ));
569 WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get()); 515 WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get());
570 return base::SysWideToUTF8(value_string); 516 return base::SysWideToUTF8(value_string);
571 } 517 }
572 518
573 DWORD DeviceRegistryPropertyValue::AsDWORD() const { 519 DWORD DeviceRegistryPropertyValue::AsDWORD() const {
574 CHECK_EQ(property_type_, static_cast<DWORD>(REG_DWORD)); 520 CHECK_EQ(property_type_, static_cast<DWORD>(REG_DWORD));
575 DWORD* value = reinterpret_cast<DWORD*>(value_.get()); 521 DWORD* value = reinterpret_cast<DWORD*>(value_.get());
576 return *value; 522 return *value;
577 } 523 }
578 524
579 DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type, 525 DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type,
580 scoped_ptr<uint8_t[]> value, 526 scoped_ptr<uint8_t[]> value,
581 size_t value_size) 527 size_t value_size)
582 : property_type_(property_type), 528 : property_type_(property_type),
583 value_(value.Pass()), 529 value_(value.Pass()),
584 value_size_(value_size) { 530 value_size_(value_size) {}
585 }
586 531
587 DevicePropertyValue::~DevicePropertyValue() { 532 DevicePropertyValue::~DevicePropertyValue() {}
588 }
589 533
590 uint32_t DevicePropertyValue::AsUint32() const { 534 uint32_t DevicePropertyValue::AsUint32() const {
591 CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32)); 535 CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32));
592 CHECK_EQ(value_size_, sizeof(uint32_t)); 536 CHECK_EQ(value_size_, sizeof(uint32_t));
593 return *reinterpret_cast<uint32_t*>(value_.get()); 537 return *reinterpret_cast<uint32_t*>(value_.get());
594 } 538 }
595 539
596 BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() { 540 BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() {}
597 }
598 541
599 BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() { 542 BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() {}
600 }
601 543
602 BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo() 544 BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo()
603 : visible(false), authenticated(false), connected(false) { 545 : visible(false), authenticated(false), connected(false) {
604 address.ullLong = BLUETOOTH_NULL_ADDRESS; 546 address.ullLong = BLUETOOTH_NULL_ADDRESS;
605 } 547 }
606 548
607 BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() { 549 BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() {}
608 }
609 550
610 bool IsBluetoothLowEnergySupported() { 551 bool IsBluetoothLowEnergySupported() {
611 return base::win::GetVersion() >= base::win::VERSION_WIN8; 552 return base::win::GetVersion() >= base::win::VERSION_WIN8;
612 } 553 }
613 554
614 bool EnumerateKnownBluetoothLowEnergyDevices( 555 bool EnumerateKnownBluetoothLowEnergyDevices(
556 GUID guid,
615 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, 557 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
616 std::string* error) { 558 std::string* error) {
617 if (!IsBluetoothLowEnergySupported()) { 559 if (!IsBluetoothLowEnergySupported()) {
618 *error = kPlatformNotSupported; 560 *error = kPlatformNotSupported;
619 return false; 561 return false;
620 } 562 }
621 563
622 ScopedDeviceInfoSetHandle info_set_handle; 564 ScopedDeviceInfoSetHandle info_set_handle;
623 HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle); 565 HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle, guid);
624 if (FAILED(hr)) { 566 if (FAILED(hr)) {
625 *error = FormatBluetoothError(kDeviceEnumError, hr); 567 *error = FormatBluetoothError(kDeviceEnumError, hr);
626 return false; 568 return false;
627 } 569 }
628 570
629 for (DWORD i = 0;; ++i) { 571 for (DWORD i = 0;; ++i) {
630 scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info; 572 scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info;
631 DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice( 573 DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice(
632 info_set_handle, i, &device_info, error); 574 guid, info_set_handle, i, &device_info, error);
633 switch (result) { 575 switch (result) {
634 case kNoMoreDevices: 576 case kNoMoreDevices:
635 return true; 577 return true;
636 case kError: 578 case kError:
637 return false; 579 return false;
638 case kOk: 580 case kOk:
639 devices->push_back(device_info.Pass()); 581 devices->push_back(device_info.Pass());
640 } 582 }
641 } 583 }
642 } 584 }
(...skipping 10 matching lines...) Expand all
653 return CollectBluetoothLowEnergyDeviceServices(device_path, services, error); 595 return CollectBluetoothLowEnergyDeviceServices(device_path, services, error);
654 } 596 }
655 597
656 bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting( 598 bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting(
657 const std::string& instance_id, 599 const std::string& instance_id,
658 BLUETOOTH_ADDRESS* btha, 600 BLUETOOTH_ADDRESS* btha,
659 std::string* error) { 601 std::string* error) {
660 return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error); 602 return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error);
661 } 603 }
662 604
605 HRESULT ReadPrimaryServicesOfADevice(HANDLE device_handle,
606 BTH_LE_GATT_SERVICE** out_primary_services,
607 USHORT* out_counts) {
608 USHORT required_length = 0;
609 HRESULT hr = BluetoothGATTGetServices(
610 device_handle, 0, NULL, &required_length, BLUETOOTH_GATT_FLAG_NONE);
611 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
612 return hr;
613 }
614
615 *out_primary_services = new BTH_LE_GATT_SERVICE[required_length];
616 USHORT actual_length = required_length;
617 hr = BluetoothGATTGetServices(device_handle, actual_length,
618 *out_primary_services, &required_length,
619 BLUETOOTH_GATT_FLAG_NONE);
620 if (SUCCEEDED(hr) && required_length != actual_length) {
621 LOG(ERROR) << "Retrieved primary services is not equal to expected"
622 << " actual_length " << actual_length << " required_length "
623 << required_length;
624 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
625 }
626
627 *out_counts = actual_length;
628 if (FAILED(hr)) {
629 delete *out_primary_services;
630 *out_counts = 0;
631 }
632 return hr;
633 }
634
635 HRESULT ReadCharacteristicsOfAService(
636 HANDLE device_handle,
637 const PBTH_LE_GATT_SERVICE service,
638 BTH_LE_GATT_CHARACTERISTIC** out_included_characteristics,
639 USHORT* out_counts) {
640 USHORT required_length = 0;
641 HRESULT hr = BluetoothGATTGetCharacteristics(device_handle, service, 0, NULL,
642 &required_length,
643 BLUETOOTH_GATT_FLAG_NONE);
644 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
645 return hr;
646 }
647
648 *out_included_characteristics =
649 new BTH_LE_GATT_CHARACTERISTIC[required_length];
650 USHORT actual_length = required_length;
651 hr = BluetoothGATTGetCharacteristics(
652 device_handle, service, actual_length, *out_included_characteristics,
653 &required_length, BLUETOOTH_GATT_FLAG_NONE);
654 if (SUCCEEDED(hr) && required_length != actual_length) {
655 LOG(ERROR) << "Retrieved charactersitics is not equal to expected"
656 << " actual_length " << actual_length << " required_length "
657 << required_length;
658 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
659 }
660
661 *out_counts = actual_length;
662 if (FAILED(hr)) {
663 delete *out_included_characteristics;
664 *out_counts = 0;
665 }
666 return hr;
667 }
668
669 HRESULT ReadIncludedServicesOfAService(
670 HANDLE device_handle,
671 const PBTH_LE_GATT_SERVICE service,
672 BTH_LE_GATT_SERVICE** out_included_services,
673 USHORT* out_counts) {
674 USHORT required_length = 0;
675 HRESULT hr = BluetoothGATTGetIncludedServices(device_handle, service, 0, NULL,
676 &required_length,
677 BLUETOOTH_GATT_FLAG_NONE);
678 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
679 return hr;
680 }
681
682 *out_included_services = new BTH_LE_GATT_SERVICE[required_length];
683 USHORT actual_length = required_length;
684 hr = BluetoothGATTGetIncludedServices(
685 device_handle, service, actual_length, *out_included_services,
686 &required_length, BLUETOOTH_GATT_FLAG_NONE);
687 if (SUCCEEDED(hr) && required_length != actual_length) {
688 LOG(ERROR) << "Retrieved included services is not equal to expected"
689 << " actual_length " << actual_length << " required_length "
690 << required_length;
691 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
692 }
693
694 *out_counts = actual_length;
695 if (FAILED(hr)) {
696 delete *out_included_services;
697 *out_counts = 0;
698 }
699 return hr;
700 }
701
702 HRESULT ReadTheValueOfACharacteristic(
703 HANDLE device_handle,
704 const PBTH_LE_GATT_CHARACTERISTIC characteristic,
705 BTH_LE_GATT_CHARACTERISTIC_VALUE** out_characteristic_value) {
706 USHORT required_length = 0;
707 HRESULT hr = BluetoothGATTGetCharacteristicValue(
708 device_handle, characteristic, 0, NULL, &required_length,
709 BLUETOOTH_GATT_FLAG_NONE);
710 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
711 return hr;
712 }
713
714 *out_characteristic_value =
715 (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(new UCHAR[required_length]);
716 USHORT actual_length = required_length;
717 hr = BluetoothGATTGetCharacteristicValue(
718 device_handle, characteristic, (ULONG)required_length,
719 *out_characteristic_value, &actual_length, BLUETOOTH_GATT_FLAG_NONE);
720 if (SUCCEEDED(hr) && required_length != actual_length) {
721 LOG(ERROR) << "Retrieved characteristic value size is not equal to expected"
722 << " actual_length " << actual_length << " required_length "
723 << required_length;
724 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
725 }
726
727 if (FAILED(hr)) {
728 delete *out_characteristic_value;
729 }
730 return hr;
731 }
732
733 HRESULT WriteTheValueOfACharacteristic(
734 HANDLE device_handle,
735 const PBTH_LE_GATT_CHARACTERISTIC characteristic,
736 BTH_LE_GATT_CHARACTERISTIC_VALUE* new_value) {
737 return BluetoothGATTSetCharacteristicValue(
738 device_handle, characteristic, new_value, NULL, BLUETOOTH_GATT_FLAG_NONE);
739 }
740
741 HRESULT ReliableWriteTheValueOfACharacteristic(
742 HANDLE device_handle,
743 const PBTH_LE_GATT_CHARACTERISTIC characteristic,
744 BTH_LE_GATT_CHARACTERISTIC_VALUE* new_value) {
745 BTH_LE_GATT_RELIABLE_WRITE_CONTEXT reliable_write_context = NULL;
746 HRESULT hr = BluetoothGATTBeginReliableWrite(
747 device_handle, &reliable_write_context, BLUETOOTH_GATT_FLAG_NONE);
748 if (FAILED(hr))
749 return hr;
750
751 hr = BluetoothGATTSetCharacteristicValue(
752 device_handle, characteristic, new_value, NULL, BLUETOOTH_GATT_FLAG_NONE);
753 if (NULL != reliable_write_context) {
754 BluetoothGATTEndReliableWrite(device_handle, reliable_write_context,
755 BLUETOOTH_GATT_FLAG_NONE);
756 }
757
758 return hr;
759 }
760
761 HRESULT ReadDescriptorsOfACharacteristic(
762 HANDLE device_handle,
763 const PBTH_LE_GATT_CHARACTERISTIC characteristic,
764 BTH_LE_GATT_DESCRIPTOR** out_included_descriptors,
765 USHORT* out_counts) {
766 USHORT required_length = 0;
767 HRESULT hr =
768 BluetoothGATTGetDescriptors(device_handle, characteristic, 0, NULL,
769 &required_length, BLUETOOTH_GATT_FLAG_NONE);
770 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
771 return hr;
772 }
773
774 *out_included_descriptors = new BTH_LE_GATT_DESCRIPTOR[required_length];
775 USHORT actual_length = required_length;
776 hr = BluetoothGATTGetDescriptors(device_handle, characteristic, actual_length,
777 *out_included_descriptors, &required_length,
778 BLUETOOTH_GATT_FLAG_NONE);
779 if (SUCCEEDED(hr) && required_length != actual_length) {
780 LOG(ERROR) << "Retrieved # of descriptors is not equal to expected"
781 << " actual_length " << actual_length << " required_length "
782 << required_length;
783 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
784 }
785
786 *out_counts = actual_length;
787 if (FAILED(hr)) {
788 delete *out_included_descriptors;
789 *out_counts = 0;
790 }
791 return hr;
792 }
793
794 HRESULT ReadTheValueOfADescriptor(HANDLE device_handle,
795 const PBTH_LE_GATT_DESCRIPTOR descriptor,
796 BTH_LE_GATT_DESCRIPTOR_VALUE** out_value) {
797 USHORT required_length = 0;
798 HRESULT hr = BluetoothGATTGetDescriptorValue(device_handle, descriptor, 0,
799 NULL, &required_length,
800 BLUETOOTH_GATT_FLAG_NONE);
801 if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
802 return hr;
803 }
804
805 *out_value = (PBTH_LE_GATT_DESCRIPTOR_VALUE)(new UCHAR[required_length]);
806 USHORT actual_length = required_length;
807 hr = BluetoothGATTGetDescriptorValue(
808 device_handle, descriptor, (ULONG)actual_length, *out_value,
809 &required_length, BLUETOOTH_GATT_FLAG_NONE);
810 if (SUCCEEDED(hr) && required_length != actual_length) {
811 LOG(ERROR) << "Retrieved descriptor value size is not equal to expected"
812 << " actual_length " << actual_length << " required_length "
813 << required_length;
814 hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
815 }
816
817 if (FAILED(hr)) {
818 delete *out_value;
819 }
820 return hr;
821 }
822
823 HRESULT WriteTheDescriptorValue(HANDLE device_handle,
824 const PBTH_LE_GATT_DESCRIPTOR descriptor,
825 BTH_LE_GATT_DESCRIPTOR_VALUE* new_value) {
826 return BluetoothGATTSetDescriptorValue(device_handle, descriptor, new_value,
827 BLUETOOTH_GATT_FLAG_NONE);
828 }
829
830 HRESULT RegisterGattEvents(HANDLE device_handle,
831 BTH_LE_GATT_EVENT_TYPE type,
832 PVOID event_parameter,
833 PFNBLUETOOTH_GATT_EVENT_CALLBACK callback,
834 PVOID context,
835 BLUETOOTH_GATT_EVENT_HANDLE* out_handle) {
836 return BluetoothGATTRegisterEvent(device_handle, type, event_parameter,
837 callback, context, out_handle,
838 BLUETOOTH_GATT_FLAG_NONE);
839 }
840
841 HRESULT UnregisterGattEvent(BLUETOOTH_GATT_EVENT_HANDLE event_handle) {
842 return BluetoothGATTUnregisterEvent(event_handle, BLUETOOTH_GATT_FLAG_NONE);
843 }
844
663 } // namespace win 845 } // namespace win
664 } // namespace device 846 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698