OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_fake.h" | 5 #include "device/bluetooth/bluetooth_low_energy_win_fake.h" |
6 | 6 |
7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "device/bluetooth/bluetooth_low_energy_defs_win.h" |
8 | 9 |
9 namespace { | 10 namespace { |
10 const char kPlatformNotSupported[] = | 11 const char kPlatformNotSupported[] = |
11 "Bluetooth Low energy is only supported on Windows 8 and later."; | 12 "Bluetooth Low energy is only supported on Windows 8 and later."; |
12 } // namespace | 13 } // namespace |
13 | 14 |
14 namespace device { | 15 namespace device { |
15 namespace win { | 16 namespace win { |
16 | 17 |
17 BLEDevice::BLEDevice() {} | 18 BLEDevice::BLEDevice() {} |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 const base::FilePath& device_path, | 75 const base::FilePath& device_path, |
75 ScopedVector<BluetoothLowEnergyServiceInfo>* services, | 76 ScopedVector<BluetoothLowEnergyServiceInfo>* services, |
76 std::string* error) { | 77 std::string* error) { |
77 if (!IsBluetoothLowEnergySupported()) { | 78 if (!IsBluetoothLowEnergySupported()) { |
78 *error = kPlatformNotSupported; | 79 *error = kPlatformNotSupported; |
79 return false; | 80 return false; |
80 } | 81 } |
81 | 82 |
82 base::string16 device_address = | 83 base::string16 device_address = |
83 ExtractDeviceAddressFromDevicePath(device_path.value()); | 84 ExtractDeviceAddressFromDevicePath(device_path.value()); |
84 base::string16 service_attribute_handle = | 85 std::vector<std::string> service_attribute_handles = |
85 ExtractServiceAttributeHandleFromDevicePath(device_path.value()); | 86 ExtractServiceAttributeHandlesFromDevicePath(device_path.value()); |
86 | 87 |
87 BLEDevicesMap::iterator it_d = simulated_devices_.find( | 88 BLEDevicesMap::iterator it_d = simulated_devices_.find( |
88 std::string(device_address.begin(), device_address.end())); | 89 std::string(device_address.begin(), device_address.end())); |
89 CHECK(it_d != simulated_devices_.end()); | 90 CHECK(it_d != simulated_devices_.end()); |
90 | 91 |
91 // |service_attribute_handle| is empty means |device_path| is a BLE device | 92 // |service_attribute_handles| is empty means |device_path| is a BLE device |
92 // path, otherwise it is a BLE GATT service device path. | 93 // path, otherwise it is a BLE GATT service device path. |
93 if (service_attribute_handle.empty()) { | 94 if (service_attribute_handles.empty()) { |
94 // Return all primary services for BLE device. | 95 // Return all primary services for BLE device. |
95 for (auto& primary_service : it_d->second->primary_services) { | 96 for (auto& primary_service : it_d->second->primary_services) { |
96 BluetoothLowEnergyServiceInfo* service_info = | 97 BluetoothLowEnergyServiceInfo* service_info = |
97 new BluetoothLowEnergyServiceInfo(); | 98 new BluetoothLowEnergyServiceInfo(); |
98 service_info->uuid = primary_service.second->service_info->ServiceUuid; | 99 service_info->uuid = primary_service.second->service_info->ServiceUuid; |
99 service_info->attribute_handle = | 100 service_info->attribute_handle = |
100 primary_service.second->service_info->AttributeHandle; | 101 primary_service.second->service_info->AttributeHandle; |
101 services->push_back(service_info); | 102 services->push_back(service_info); |
102 } | 103 } |
103 } else { | 104 } else { |
104 // Return corresponding GATT service for BLE GATT service device. | 105 // Return corresponding GATT service for BLE GATT service device. |
105 BLEGattServicesMap::iterator it_s = | 106 BLEGattService* target_service = |
106 it_d->second->primary_services.find(std::string( | 107 GetSimulatedGattService(it_d->second.get(), service_attribute_handles); |
107 service_attribute_handle.begin(), service_attribute_handle.end())); | |
108 CHECK(it_s != it_d->second->primary_services.end()); | |
109 BluetoothLowEnergyServiceInfo* service_info = | 108 BluetoothLowEnergyServiceInfo* service_info = |
110 new BluetoothLowEnergyServiceInfo(); | 109 new BluetoothLowEnergyServiceInfo(); |
111 service_info->uuid = it_s->second->service_info->ServiceUuid; | 110 service_info->uuid = target_service->service_info->ServiceUuid; |
112 service_info->attribute_handle = | 111 service_info->attribute_handle = |
113 it_s->second->service_info->AttributeHandle; | 112 target_service->service_info->AttributeHandle; |
114 services->push_back(service_info); | 113 services->push_back(service_info); |
115 } | 114 } |
116 | 115 |
117 return true; | 116 return true; |
118 } | 117 } |
119 | 118 |
| 119 HRESULT BluetoothLowEnergyWrapperFake::ReadIncludedServicesOfAService( |
| 120 base::FilePath& service_path, |
| 121 const PBTH_LE_GATT_SERVICE service, |
| 122 scoped_ptr<BTH_LE_GATT_SERVICE>* out_included_services, |
| 123 USHORT* out_counts) { |
| 124 base::string16 device_address = |
| 125 ExtractDeviceAddressFromDevicePath(service_path.value()); |
| 126 std::vector<std::string> service_att_handles = |
| 127 ExtractServiceAttributeHandlesFromDevicePath(service_path.value()); |
| 128 BLEGattService* target_service = GetSimulatedGattService( |
| 129 GetSimulatedBLEDevice( |
| 130 std::string(device_address.begin(), device_address.end())), |
| 131 service_att_handles); |
| 132 if (target_service == nullptr) |
| 133 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); |
| 134 |
| 135 std::size_t number_of_included_services = |
| 136 target_service->included_services.size(); |
| 137 if (number_of_included_services) { |
| 138 *out_counts = (USHORT)number_of_included_services; |
| 139 (*out_included_services) |
| 140 .reset(new BTH_LE_GATT_SERVICE[number_of_included_services]); |
| 141 std::size_t i = 0; |
| 142 for (const auto& service : target_service->included_services) { |
| 143 (*out_included_services).get()[i].ServiceUuid = |
| 144 service.second->service_info->ServiceUuid; |
| 145 (*out_included_services).get()[i].AttributeHandle = |
| 146 service.second->service_info->AttributeHandle; |
| 147 i++; |
| 148 } |
| 149 return S_OK; |
| 150 } |
| 151 return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); |
| 152 } |
| 153 |
| 154 HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicsOfAService( |
| 155 base::FilePath& service_path, |
| 156 const PBTH_LE_GATT_SERVICE service, |
| 157 scoped_ptr<BTH_LE_GATT_CHARACTERISTIC>* out_included_characteristics, |
| 158 USHORT* out_counts) { |
| 159 base::string16 device_address = |
| 160 ExtractDeviceAddressFromDevicePath(service_path.value()); |
| 161 const std::vector<std::string> service_att_handles = |
| 162 ExtractServiceAttributeHandlesFromDevicePath(service_path.value()); |
| 163 BLEGattService* target_service = GetSimulatedGattService( |
| 164 GetSimulatedBLEDevice( |
| 165 std::string(device_address.begin(), device_address.end())), |
| 166 service_att_handles); |
| 167 if (target_service == nullptr) |
| 168 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); |
| 169 |
| 170 std::size_t number_of_included_characteristic = |
| 171 target_service->included_characteristics.size(); |
| 172 if (number_of_included_characteristic) { |
| 173 *out_counts = (USHORT)number_of_included_characteristic; |
| 174 (*out_included_characteristics) |
| 175 .reset( |
| 176 new BTH_LE_GATT_CHARACTERISTIC[number_of_included_characteristic]); |
| 177 std::size_t i = 0; |
| 178 for (const auto& cha : target_service->included_characteristics) { |
| 179 (*out_included_characteristics).get()[i] = |
| 180 *(cha.second->characteristic_info); |
| 181 i++; |
| 182 } |
| 183 return S_OK; |
| 184 } |
| 185 return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); |
| 186 } |
| 187 |
120 BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( | 188 BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( |
121 std::string device_name, | 189 std::string device_name, |
122 BLUETOOTH_ADDRESS device_address) { | 190 BLUETOOTH_ADDRESS device_address) { |
123 BLEDevice* device = new BLEDevice(); | 191 BLEDevice* device = new BLEDevice(); |
124 BluetoothLowEnergyDeviceInfo* device_info = | 192 BluetoothLowEnergyDeviceInfo* device_info = |
125 new BluetoothLowEnergyDeviceInfo(); | 193 new BluetoothLowEnergyDeviceInfo(); |
126 std::string string_device_address = | 194 std::string string_device_address = |
127 BluetoothAddressToCanonicalString(device_address); | 195 BluetoothAddressToCanonicalString(device_address); |
128 device_info->path = | 196 device_info->path = |
129 base::FilePath(GenerateBLEDevicePath(string_device_address)); | 197 base::FilePath(GenerateBLEDevicePath(string_device_address)); |
130 device_info->friendly_name = device_name; | 198 device_info->friendly_name = device_name; |
131 device_info->address = device_address; | 199 device_info->address = device_address; |
132 device->device_info.reset(device_info); | 200 device->device_info.reset(device_info); |
133 simulated_devices_[string_device_address] = make_scoped_ptr(device); | 201 simulated_devices_[string_device_address] = make_scoped_ptr(device); |
134 return device; | 202 return device; |
135 } | 203 } |
136 | 204 |
| 205 BLEDevice* BluetoothLowEnergyWrapperFake::GetSimulatedBLEDevice( |
| 206 std::string device_address) { |
| 207 BLEDevicesMap::iterator it_d = simulated_devices_.find(device_address); |
| 208 if (it_d == simulated_devices_.end()) |
| 209 return nullptr; |
| 210 return it_d->second.get(); |
| 211 } |
| 212 |
137 BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( | 213 BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( |
138 BLEDevice* device, | 214 BLEDevice* device, |
139 std::string uuid) { | 215 BLEGattService* parent_service, |
| 216 const BTH_LE_UUID& uuid) { |
140 CHECK(device); | 217 CHECK(device); |
141 | 218 |
142 BLEGattService* service = new BLEGattService(); | 219 BLEGattService* service = new BLEGattService(); |
143 PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; | 220 PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; |
144 std::string string_device_address = | 221 std::string string_device_address = |
145 BluetoothAddressToCanonicalString(device->device_info->address); | 222 BluetoothAddressToCanonicalString(device->device_info->address); |
146 service_info->AttributeHandle = | 223 service_info->AttributeHandle = |
147 GenerateAUniqueAttributeHandle(string_device_address); | 224 GenerateAUniqueAttributeHandle(string_device_address); |
148 service_info->ServiceUuid = CanonicalStringToBTH_LE_UUID(uuid); | 225 service_info->ServiceUuid = uuid; |
149 service->service_info.reset(service_info); | 226 service->service_info.reset(service_info); |
150 device->primary_services[std::to_string(service_info->AttributeHandle)] = | 227 |
151 make_scoped_ptr(service); | 228 if (parent_service) { |
| 229 parent_service |
| 230 ->included_services[std::to_string(service_info->AttributeHandle)] = |
| 231 make_scoped_ptr(service); |
| 232 } else { |
| 233 device->primary_services[std::to_string(service_info->AttributeHandle)] = |
| 234 make_scoped_ptr(service); |
| 235 } |
152 return service; | 236 return service; |
153 } | 237 } |
154 | 238 |
155 BLEDevice* BluetoothLowEnergyWrapperFake::GetSimulatedBLEDevice( | 239 void BluetoothLowEnergyWrapperFake::SimulateBLEGattServiceRemove( |
156 std::string device_address) { | 240 BLEDevice* device, |
157 BLEDevicesMap::iterator it_d = simulated_devices_.find(device_address); | 241 BLEGattService* parent_service, |
158 if (it_d == simulated_devices_.end()) | 242 std::string attribute_handle) { |
| 243 if (parent_service) { |
| 244 parent_service->included_services.erase(attribute_handle); |
| 245 } else { |
| 246 device->primary_services.erase(attribute_handle); |
| 247 } |
| 248 } |
| 249 |
| 250 BLEGattService* BluetoothLowEnergyWrapperFake::GetSimulatedGattService( |
| 251 BLEDevice* device, |
| 252 const std::vector<std::string>& chain_of_att_handle) { |
| 253 // First, find the root primary service. |
| 254 BLEGattServicesMap::iterator it_s = |
| 255 device->primary_services.find(chain_of_att_handle[0]); |
| 256 if (it_s == device->primary_services.end()) |
159 return nullptr; | 257 return nullptr; |
160 return it_d->second.get(); | 258 |
| 259 // Iteratively follow the chain of included service attribute handles to find |
| 260 // the target service. |
| 261 for (std::size_t i = 1; i < chain_of_att_handle.size(); i++) { |
| 262 std::string included_att_handle = std::string( |
| 263 chain_of_att_handle[i].begin(), chain_of_att_handle[i].end()); |
| 264 BLEGattServicesMap::iterator it_i = |
| 265 it_s->second->included_services.find(included_att_handle); |
| 266 if (it_i == it_s->second->included_services.end()) |
| 267 return nullptr; |
| 268 it_s = it_i; |
| 269 } |
| 270 return it_s->second.get(); |
| 271 } |
| 272 |
| 273 BLEGattCharacteristic* BluetoothLowEnergyWrapperFake::SimulateCharacterisc( |
| 274 std::string device_address, |
| 275 BLEGattService* parent_service, |
| 276 const BTH_LE_GATT_CHARACTERISTIC& characteristic) { |
| 277 CHECK(parent_service); |
| 278 |
| 279 BLEGattCharacteristic* cha = new BLEGattCharacteristic(); |
| 280 PBTH_LE_GATT_CHARACTERISTIC win_cha_info = new BTH_LE_GATT_CHARACTERISTIC[1]; |
| 281 *win_cha_info = characteristic; |
| 282 (cha->characteristic_info).reset(win_cha_info); |
| 283 cha->characteristic_info->AttributeHandle = |
| 284 GenerateAUniqueAttributeHandle(device_address); |
| 285 parent_service->included_characteristics[std::to_string( |
| 286 cha->characteristic_info->AttributeHandle)] = make_scoped_ptr(cha); |
| 287 return cha; |
| 288 } |
| 289 |
| 290 void BluetoothLowEnergyWrapperFake::SimulateCharacteriscRemove( |
| 291 BLEGattService* parent_service, |
| 292 std::string attribute_handle) { |
| 293 CHECK(parent_service); |
| 294 parent_service->included_characteristics.erase(attribute_handle); |
161 } | 295 } |
162 | 296 |
163 USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle( | 297 USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle( |
164 std::string device_address) { | 298 std::string device_address) { |
165 scoped_ptr<std::set<USHORT>>& set_of_ushort = | 299 scoped_ptr<std::set<USHORT>>& set_of_ushort = |
166 attribute_handle_table_[device_address]; | 300 attribute_handle_table_[device_address]; |
167 if (set_of_ushort) { | 301 if (set_of_ushort) { |
168 USHORT max_attribute_handle = *set_of_ushort->rbegin(); | 302 USHORT max_attribute_handle = *set_of_ushort->rbegin(); |
169 if (max_attribute_handle < 0xFFFF) { | 303 if (max_attribute_handle < 0xFFFF) { |
170 USHORT new_attribute_handle = max_attribute_handle + 1; | 304 USHORT new_attribute_handle = max_attribute_handle + 1; |
(...skipping 28 matching lines...) Expand all Loading... |
199 base::string16 resident_device_path, | 333 base::string16 resident_device_path, |
200 USHORT service_attribute_handle) { | 334 USHORT service_attribute_handle) { |
201 std::string sub_path = std::to_string(service_attribute_handle); | 335 std::string sub_path = std::to_string(service_attribute_handle); |
202 return resident_device_path + L"/" + | 336 return resident_device_path + L"/" + |
203 base::string16(sub_path.begin(), sub_path.end()); | 337 base::string16(sub_path.begin(), sub_path.end()); |
204 } | 338 } |
205 | 339 |
206 base::string16 | 340 base::string16 |
207 BluetoothLowEnergyWrapperFake::ExtractDeviceAddressFromDevicePath( | 341 BluetoothLowEnergyWrapperFake::ExtractDeviceAddressFromDevicePath( |
208 base::string16 path) { | 342 base::string16 path) { |
209 std::size_t found = path.find('/'); | 343 std::size_t found = path.find_first_of('/'); |
210 if (found != base::string16::npos) { | 344 if (found != base::string16::npos) { |
211 return path.substr(0, found); | 345 return path.substr(0, found); |
212 } | 346 } |
213 return path; | 347 return path; |
214 } | 348 } |
215 | 349 |
216 base::string16 | 350 std::vector<std::string> |
217 BluetoothLowEnergyWrapperFake::ExtractServiceAttributeHandleFromDevicePath( | 351 BluetoothLowEnergyWrapperFake::ExtractServiceAttributeHandlesFromDevicePath( |
218 base::string16 path) { | 352 base::string16 path) { |
219 std::size_t found = path.find('/'); | 353 std::size_t found = path.find('/'); |
220 if (found == base::string16::npos) | 354 if (found == base::string16::npos) |
221 return base::string16(); | 355 return std::vector<std::string>(); |
222 return path.substr(found + 1); | |
223 } | |
224 | 356 |
225 BTH_LE_UUID BluetoothLowEnergyWrapperFake::CanonicalStringToBTH_LE_UUID( | 357 std::vector<std::string> chain_of_att_handle; |
226 std::string uuid) { | 358 while (true) { |
227 BTH_LE_UUID win_uuid; | 359 std::size_t next_found = path.find(path, found + 1); |
228 // Only short UUIDs (4 hex digits) have beened used in BluetoothTest right | 360 if (next_found == base::string16::npos) |
229 // now. Need fix after using long UUIDs. | 361 break; |
230 win_uuid.IsShortUuid = true; | 362 base::string16 w_att_handle = path.substr(found + 1, next_found); |
231 unsigned int data[1]; | 363 chain_of_att_handle.push_back( |
232 int result = sscanf_s(uuid.c_str(), "%04x", &data[0]); | 364 std::string(w_att_handle.begin(), w_att_handle.end())); |
233 CHECK(result == 1); | 365 found = next_found; |
234 win_uuid.Value.ShortUuid = data[0]; | 366 } |
235 return win_uuid; | 367 base::string16 w_att_handle = path.substr(found + 1); |
| 368 chain_of_att_handle.push_back( |
| 369 std::string(w_att_handle.begin(), w_att_handle.end())); |
| 370 return chain_of_att_handle; |
236 } | 371 } |
237 | 372 |
238 std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString( | 373 std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString( |
239 const BLUETOOTH_ADDRESS& btha) { | 374 const BLUETOOTH_ADDRESS& btha) { |
240 std::string result = base::StringPrintf( | 375 std::string result = base::StringPrintf( |
241 "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4], | 376 "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4], |
242 btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]); | 377 btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]); |
243 return result; | 378 return result; |
244 } | 379 } |
245 | 380 |
246 } // namespace win | 381 } // namespace win |
247 } // namespace device | 382 } // namespace device |
OLD | NEW |