OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |