| 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/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
| 10 #include "base/win/windows_version.h" | 9 #include "base/win/windows_version.h" |
| 11 | 10 |
| 12 namespace { | 11 namespace { |
| 13 | 12 |
| 13 using device::win::DeviceRegistryPropertyValue; |
| 14 |
| 14 const char kPlatformNotSupported[] = | 15 const char kPlatformNotSupported[] = |
| 15 "Bluetooth Low energy is only supported on Windows 8 and later."; | 16 "Bluetooth Low energy is only supported on Windows 8 and later."; |
| 16 const char kDeviceEnumError[] = "Error enumerating Bluetooth LE devices."; | 17 const char kDeviceEnumError[] = "Error enumerating Bluetooth LE devices."; |
| 17 const char kDeviceInfoError[] = | 18 const char kDeviceInfoError[] = |
| 18 "Error retrieving Bluetooth LE device information."; | 19 "Error retrieving Bluetooth LE device information."; |
| 19 const char kDeviceAddressError[] = | 20 const char kDeviceAddressError[] = |
| 20 "Device instance ID value does not seem to contain a Bluetooth Adapter " | 21 "Device instance ID value does not seem to contain a Bluetooth Adapter " |
| 21 "address."; | 22 "address."; |
| 23 const char kDeviceFriendlyNameError[] = "Device name is not valid."; |
| 22 const char kInvalidBluetoothAddress[] = "Bluetooth address format is invalid."; | 24 const char kInvalidBluetoothAddress[] = "Bluetooth address format is invalid."; |
| 23 | 25 |
| 24 // Like ScopedHandle but for HDEVINFO. Only use this on HDEVINFO returned from | 26 // Like ScopedHandle but for HDEVINFO. Only use this on HDEVINFO returned from |
| 25 // SetupDiGetClassDevs. | 27 // SetupDiGetClassDevs. |
| 26 class DeviceInfoSetTraits { | 28 class DeviceInfoSetTraits { |
| 27 public: | 29 public: |
| 28 typedef HDEVINFO Handle; | 30 typedef HDEVINFO Handle; |
| 29 | 31 |
| 30 static bool CloseHandle(HDEVINFO handle) { | 32 static bool CloseHandle(HDEVINFO handle) { |
| 31 return ::SetupDiDestroyDeviceInfoList(handle) != FALSE; | 33 return ::SetupDiDestroyDeviceInfoList(handle) != FALSE; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 const char* message, | 118 const char* message, |
| 117 std::string* error) { | 119 std::string* error) { |
| 118 if (actual_length != expected_length) { | 120 if (actual_length != expected_length) { |
| 119 *error = FormatBluetoothError(message, E_FAIL); | 121 *error = FormatBluetoothError(message, E_FAIL); |
| 120 return false; | 122 return false; |
| 121 } | 123 } |
| 122 | 124 |
| 123 return true; | 125 return true; |
| 124 } | 126 } |
| 125 | 127 |
| 126 // Represents a device registry property value | |
| 127 class DeviceRegistryPropertyValue { | |
| 128 public: | |
| 129 static scoped_ptr<DeviceRegistryPropertyValue> | |
| 130 Create(DWORD property_type, scoped_ptr<UINT8[]> value, size_t value_size) { | |
| 131 if (property_type == REG_SZ) { | |
| 132 // Ensure string is zero terminated. | |
| 133 size_t character_size = value_size / sizeof(WCHAR); | |
| 134 CHECK_EQ(character_size * sizeof(WCHAR), value_size); | |
| 135 CHECK_GE(character_size, 1u); | |
| 136 WCHAR* value_string = reinterpret_cast<WCHAR*>(value.get()); | |
| 137 value_string[character_size - 1] = 0; | |
| 138 } | |
| 139 return scoped_ptr<DeviceRegistryPropertyValue>( | |
| 140 new DeviceRegistryPropertyValue( | |
| 141 property_type, value.Pass(), value_size)); | |
| 142 } | |
| 143 | |
| 144 bool AsString(std::string* value, std::string* error) { | |
| 145 if (property_type_ != REG_SZ) { | |
| 146 *error = "Property is not a string"; | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get()); | |
| 151 *value = base::SysWideToUTF8(value_string); | |
| 152 return true; | |
| 153 } | |
| 154 | |
| 155 private: | |
| 156 DeviceRegistryPropertyValue(DWORD property_type, | |
| 157 scoped_ptr<UINT8[]> value, | |
| 158 size_t value_size) | |
| 159 : property_type_(property_type), | |
| 160 value_(value.Pass()), | |
| 161 value_size_(value_size) {} | |
| 162 | |
| 163 DWORD property_type_; | |
| 164 scoped_ptr<UINT8[]> value_; | |
| 165 size_t value_size_; | |
| 166 | |
| 167 DISALLOW_COPY_AND_ASSIGN(DeviceRegistryPropertyValue); | |
| 168 }; | |
| 169 | |
| 170 bool CollectBluetoothLowEnergyDeviceRegistryProperty( | 128 bool CollectBluetoothLowEnergyDeviceRegistryProperty( |
| 171 const ScopedDeviceInfoSetHandle& device_info_handle, | 129 const ScopedDeviceInfoSetHandle& device_info_handle, |
| 172 PSP_DEVINFO_DATA device_info_data, | 130 PSP_DEVINFO_DATA device_info_data, |
| 173 DWORD property_id, | 131 DWORD property_id, |
| 174 scoped_ptr<DeviceRegistryPropertyValue>* value, | 132 scoped_ptr<DeviceRegistryPropertyValue>* value, |
| 175 std::string* error) { | 133 std::string* error) { |
| 176 ULONG required_length = 0; | 134 ULONG required_length = 0; |
| 177 BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle, | 135 BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle, |
| 178 device_info_data, | 136 device_info_data, |
| 179 property_id, | 137 property_id, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 std::string* error) { | 203 std::string* error) { |
| 246 scoped_ptr<DeviceRegistryPropertyValue> property_value; | 204 scoped_ptr<DeviceRegistryPropertyValue> property_value; |
| 247 if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle, | 205 if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle, |
| 248 device_info_data, | 206 device_info_data, |
| 249 SPDRP_FRIENDLYNAME, | 207 SPDRP_FRIENDLYNAME, |
| 250 &property_value, | 208 &property_value, |
| 251 error)) { | 209 error)) { |
| 252 return false; | 210 return false; |
| 253 } | 211 } |
| 254 | 212 |
| 255 if (!property_value->AsString(&device_info->friendly_name, error)) { | 213 if (property_value->property_type() != REG_SZ) { |
| 214 *error = kDeviceFriendlyNameError; |
| 256 return false; | 215 return false; |
| 257 } | 216 } |
| 258 | 217 |
| 218 device_info->friendly_name = property_value->AsString(); |
| 259 return true; | 219 return true; |
| 260 } | 220 } |
| 261 | 221 |
| 262 bool ExtractBluetoothAddressFromDeviceInstanceId(const std::string& instance_id, | 222 bool ExtractBluetoothAddressFromDeviceInstanceId(const std::string& instance_id, |
| 263 BLUETOOTH_ADDRESS* btha, | 223 BLUETOOTH_ADDRESS* btha, |
| 264 std::string* error) { | 224 std::string* error) { |
| 265 size_t start = instance_id.find("_"); | 225 size_t start = instance_id.find("_"); |
| 266 if (start == std::string::npos) { | 226 if (start == std::string::npos) { |
| 267 *error = kDeviceAddressError; | 227 *error = kDeviceAddressError; |
| 268 return false; | 228 return false; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 | 373 |
| 414 (*handle) = result.Pass(); | 374 (*handle) = result.Pass(); |
| 415 return S_OK; | 375 return S_OK; |
| 416 } | 376 } |
| 417 | 377 |
| 418 } // namespace | 378 } // namespace |
| 419 | 379 |
| 420 namespace device { | 380 namespace device { |
| 421 namespace win { | 381 namespace win { |
| 422 | 382 |
| 383 // static |
| 384 scoped_ptr<DeviceRegistryPropertyValue> DeviceRegistryPropertyValue::Create( |
| 385 DWORD property_type, |
| 386 scoped_ptr<uint8_t[]> value, |
| 387 size_t value_size) { |
| 388 switch (property_type) { |
| 389 case REG_SZ: { |
| 390 // Ensure string is zero terminated. |
| 391 size_t character_size = value_size / sizeof(WCHAR); |
| 392 CHECK_EQ(character_size * sizeof(WCHAR), value_size); |
| 393 CHECK_GE(character_size, 1u); |
| 394 WCHAR* value_string = reinterpret_cast<WCHAR*>(value.get()); |
| 395 value_string[character_size - 1] = 0; |
| 396 break; |
| 397 } |
| 398 case REG_DWORD: { |
| 399 CHECK_EQ(value_size, sizeof(DWORD)); |
| 400 break; |
| 401 } |
| 402 } |
| 403 return scoped_ptr<DeviceRegistryPropertyValue>( |
| 404 new DeviceRegistryPropertyValue(property_type, value.Pass(), value_size)); |
| 405 } |
| 406 |
| 407 DeviceRegistryPropertyValue::DeviceRegistryPropertyValue( |
| 408 DWORD property_type, |
| 409 scoped_ptr<uint8_t[]> value, |
| 410 size_t value_size) |
| 411 : property_type_(property_type), |
| 412 value_(value.Pass()), |
| 413 value_size_(value_size) { |
| 414 } |
| 415 |
| 416 DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() { |
| 417 } |
| 418 |
| 419 std::string DeviceRegistryPropertyValue::AsString() const { |
| 420 CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ)); |
| 421 WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get()); |
| 422 return base::SysWideToUTF8(value_string); |
| 423 } |
| 424 |
| 425 DWORD DeviceRegistryPropertyValue::AsDWORD() const { |
| 426 CHECK_EQ(property_type_, static_cast<DWORD>(REG_DWORD)); |
| 427 DWORD* value = reinterpret_cast<DWORD*>(value_.get()); |
| 428 return *value; |
| 429 } |
| 430 |
| 423 bool IsBluetoothLowEnergySupported() { | 431 bool IsBluetoothLowEnergySupported() { |
| 424 return base::win::GetVersion() >= base::win::VERSION_WIN8; | 432 return base::win::GetVersion() >= base::win::VERSION_WIN8; |
| 425 } | 433 } |
| 426 | 434 |
| 427 bool EnumerateKnownBluetoothLowEnergyDevices( | 435 bool EnumerateKnownBluetoothLowEnergyDevices( |
| 428 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, | 436 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
| 429 std::string* error) { | 437 std::string* error) { |
| 430 if (!IsBluetoothLowEnergySupported()) { | 438 if (!IsBluetoothLowEnergySupported()) { |
| 431 *error = kPlatformNotSupported; | 439 *error = kPlatformNotSupported; |
| 432 return false; | 440 return false; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 456 | 464 |
| 457 bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting( | 465 bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting( |
| 458 const std::string& instance_id, | 466 const std::string& instance_id, |
| 459 BLUETOOTH_ADDRESS* btha, | 467 BLUETOOTH_ADDRESS* btha, |
| 460 std::string* error) { | 468 std::string* error) { |
| 461 return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error); | 469 return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error); |
| 462 } | 470 } |
| 463 | 471 |
| 464 } // namespace win | 472 } // namespace win |
| 465 } // namespace device | 473 } // namespace device |
| OLD | NEW |