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" |
| 8 |
| 9 namespace { |
| 10 const char kPlatformNotSupported[] = |
| 11 "Bluetooth Low energy is only supported on Windows 8 and later."; |
| 12 } // namespace |
| 13 |
7 namespace device { | 14 namespace device { |
8 namespace win { | 15 namespace win { |
9 | 16 |
10 BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake() {} | 17 BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake() {} |
11 BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} | 18 BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} |
12 | 19 |
13 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices( | 20 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices( |
14 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, | 21 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
15 std::string* error) { | 22 std::string* error) { |
16 NOTIMPLEMENTED(); | 23 if (!IsBluetoothLowEnergySupported()) { |
17 return false; | 24 *error = kPlatformNotSupported; |
| 25 return false; |
| 26 } |
| 27 |
| 28 for (auto& device : simulated_devices_) { |
| 29 BluetoothLowEnergyDeviceInfo* device_info = |
| 30 new BluetoothLowEnergyDeviceInfo(); |
| 31 *device_info = *(device.second->device_info); |
| 32 devices->push_back(device_info); |
| 33 } |
| 34 return true; |
18 } | 35 } |
19 | 36 |
20 bool BluetoothLowEnergyWrapperFake:: | 37 bool BluetoothLowEnergyWrapperFake:: |
21 EnumerateKnownBluetoothLowEnergyGattServiceDevices( | 38 EnumerateKnownBluetoothLowEnergyGattServiceDevices( |
22 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, | 39 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
23 std::string* error) { | 40 std::string* error) { |
24 NOTIMPLEMENTED(); | 41 if (!IsBluetoothLowEnergySupported()) { |
25 return false; | 42 *error = kPlatformNotSupported; |
| 43 return false; |
| 44 } |
| 45 |
| 46 for (auto& device : simulated_devices_) { |
| 47 for (auto& service : device.second->primary_services) { |
| 48 BluetoothLowEnergyDeviceInfo* device_info = |
| 49 new BluetoothLowEnergyDeviceInfo(); |
| 50 *device_info = *(device.second->device_info); |
| 51 base::string16 path = GenerateBLEGattServiceDevicePath( |
| 52 device.second->device_info->path.value(), |
| 53 service.second->service_info->AttributeHandle); |
| 54 device_info->path = base::FilePath(path); |
| 55 devices->push_back(device_info); |
| 56 } |
| 57 } |
| 58 return true; |
26 } | 59 } |
27 | 60 |
28 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( | 61 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( |
29 const base::FilePath& device_path, | 62 const base::FilePath& device_path, |
30 ScopedVector<BluetoothLowEnergyServiceInfo>* services, | 63 ScopedVector<BluetoothLowEnergyServiceInfo>* services, |
31 std::string* error) { | 64 std::string* error) { |
32 NOTIMPLEMENTED(); | 65 if (!IsBluetoothLowEnergySupported()) { |
33 return false; | 66 *error = kPlatformNotSupported; |
| 67 return false; |
| 68 } |
| 69 |
| 70 base::string16 device_address = |
| 71 ExtractDeviceAddressFromDevicePath(device_path.value()); |
| 72 base::string16 service_attribute_handle = |
| 73 ExtractServiceAttributeHandleFromDevicePath(device_path.value()); |
| 74 |
| 75 BLEDevicesMap::iterator it_d = simulated_devices_.find( |
| 76 std::string(device_address.begin(), device_address.end())); |
| 77 CHECK(it_d != simulated_devices_.end()); |
| 78 |
| 79 // |service_attribute_handle| is empty means |device_path| is a BLE device |
| 80 // path, otherwise it is a BLE GATT service device path. |
| 81 if (service_attribute_handle.empty()) { |
| 82 // Return all primary services for BLE device. |
| 83 for (auto& primary_service : it_d->second->primary_services) { |
| 84 BluetoothLowEnergyServiceInfo* service_info = |
| 85 new BluetoothLowEnergyServiceInfo(); |
| 86 service_info->uuid = primary_service.second->service_info->ServiceUuid; |
| 87 service_info->attribute_handle = |
| 88 primary_service.second->service_info->AttributeHandle; |
| 89 services->push_back(service_info); |
| 90 } |
| 91 } else { |
| 92 // Return corresponding GATT service for BLE GATT service device. |
| 93 BLEGattServicesMap::iterator it_s = |
| 94 it_d->second->primary_services.find(std::string( |
| 95 service_attribute_handle.begin(), service_attribute_handle.end())); |
| 96 CHECK(it_s != it_d->second->primary_services.end()); |
| 97 BluetoothLowEnergyServiceInfo* service_info = |
| 98 new BluetoothLowEnergyServiceInfo(); |
| 99 service_info->uuid = it_s->second->service_info->ServiceUuid; |
| 100 service_info->attribute_handle = |
| 101 it_s->second->service_info->AttributeHandle; |
| 102 services->push_back(service_info); |
| 103 } |
| 104 |
| 105 return true; |
| 106 } |
| 107 |
| 108 BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( |
| 109 std::string device_name, |
| 110 BLUETOOTH_ADDRESS device_address) { |
| 111 BLEDevice* device = new BLEDevice(); |
| 112 BluetoothLowEnergyDeviceInfo* device_info = |
| 113 new BluetoothLowEnergyDeviceInfo(); |
| 114 std::string string_device_address = |
| 115 BluetoothAddressToCanonicalString(device_address); |
| 116 device_info->path = |
| 117 base::FilePath(GenerateBLEDevicePath(string_device_address)); |
| 118 device_info->friendly_name = device_name; |
| 119 device_info->address = device_address; |
| 120 device->device_info.reset(device_info); |
| 121 simulated_devices_[string_device_address] = make_scoped_ptr(device); |
| 122 return device; |
| 123 } |
| 124 |
| 125 BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( |
| 126 BLEDevice* device, |
| 127 std::string uuid) { |
| 128 CHECK(device); |
| 129 |
| 130 BLEGattService* service = new BLEGattService(); |
| 131 PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; |
| 132 std::string string_device_address = |
| 133 BluetoothAddressToCanonicalString(device->device_info->address); |
| 134 service_info->AttributeHandle = |
| 135 GenerateAUniqueAttributeHandle(string_device_address); |
| 136 service_info->ServiceUuid = CanonicalStringToBTH_LE_UUID(uuid); |
| 137 service->service_info.reset(service_info); |
| 138 device->primary_services[std::to_string(service_info->AttributeHandle)] = |
| 139 make_scoped_ptr(service); |
| 140 return service; |
| 141 } |
| 142 |
| 143 USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle( |
| 144 std::string device_address) { |
| 145 scoped_ptr<std::set<USHORT>>& set_of_ushort = |
| 146 attribute_handle_table_[device_address]; |
| 147 if (set_of_ushort) { |
| 148 USHORT max_attribute_handle = *set_of_ushort->rbegin(); |
| 149 if (max_attribute_handle < 0xFFFF) { |
| 150 USHORT new_attribute_handle = max_attribute_handle + 1; |
| 151 set_of_ushort->insert(new_attribute_handle); |
| 152 return new_attribute_handle; |
| 153 } else { |
| 154 USHORT i = 1; |
| 155 for (; i < 0xFFFF; i++) { |
| 156 if (set_of_ushort->find(i) == set_of_ushort->end()) |
| 157 break; |
| 158 } |
| 159 if (i >= 0xFFFF) |
| 160 return 0; |
| 161 set_of_ushort->insert(i); |
| 162 return i; |
| 163 } |
| 164 } |
| 165 |
| 166 USHORT smallest_att_handle = 1; |
| 167 std::set<USHORT>* new_set = new std::set<USHORT>(); |
| 168 new_set->insert(smallest_att_handle); |
| 169 set_of_ushort.reset(new_set); |
| 170 return smallest_att_handle; |
| 171 } |
| 172 |
| 173 base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEDevicePath( |
| 174 std::string device_address) { |
| 175 return base::string16(device_address.begin(), device_address.end()); |
| 176 } |
| 177 |
| 178 base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEGattServiceDevicePath( |
| 179 base::string16 resident_device_path, |
| 180 USHORT service_attribute_handle) { |
| 181 std::string sub_path = std::to_string(service_attribute_handle); |
| 182 return resident_device_path + L"/" + |
| 183 base::string16(sub_path.begin(), sub_path.end()); |
| 184 } |
| 185 |
| 186 base::string16 |
| 187 BluetoothLowEnergyWrapperFake::ExtractDeviceAddressFromDevicePath( |
| 188 base::string16 path) { |
| 189 std::size_t found = path.find('/'); |
| 190 if (found != base::string16::npos) { |
| 191 return path.substr(0, found - 1); |
| 192 } |
| 193 return path; |
| 194 } |
| 195 |
| 196 base::string16 |
| 197 BluetoothLowEnergyWrapperFake::ExtractServiceAttributeHandleFromDevicePath( |
| 198 base::string16 path) { |
| 199 std::size_t found = path.find('/'); |
| 200 if (found == base::string16::npos) |
| 201 return base::string16(); |
| 202 return path.substr(found + 1); |
| 203 } |
| 204 |
| 205 BTH_LE_UUID BluetoothLowEnergyWrapperFake::CanonicalStringToBTH_LE_UUID( |
| 206 std::string uuid) { |
| 207 BTH_LE_UUID win_uuid; |
| 208 // Only short UUIDs (4 hex digits) have beened used in BluetoothTest right |
| 209 // now. Need fix after using long UUIDs. |
| 210 win_uuid.IsShortUuid = true; |
| 211 unsigned int data[1]; |
| 212 int result = sscanf_s(uuid.c_str(), "%04x", &data[0]); |
| 213 CHECK(result == 1); |
| 214 win_uuid.Value.ShortUuid = data[0]; |
| 215 return win_uuid; |
| 216 } |
| 217 |
| 218 std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString( |
| 219 const BLUETOOTH_ADDRESS& btha) { |
| 220 std::string result = base::StringPrintf( |
| 221 "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4], |
| 222 btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]); |
| 223 return result; |
34 } | 224 } |
35 | 225 |
36 } // namespace win | 226 } // namespace win |
37 } // namespace device | 227 } // namespace device |
OLD | NEW |