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