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 |