Chromium Code Reviews| 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() { |
| 18 simulated_devices_.clear(); | |
|
scheib
2016/02/07 02:24:08
At constructor, shouldn't it already be empty()?
gogerald1
2016/02/08 19:23:50
Done.
| |
| 19 } | |
| 11 BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} | 20 BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} |
| 12 | 21 |
| 13 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices( | 22 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices( |
| 14 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, | 23 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
| 15 std::string* error) { | 24 std::string* error) { |
| 16 NOTIMPLEMENTED(); | 25 if (!IsBluetoothLowEnergySupported()) { |
| 17 return false; | 26 *error = kPlatformNotSupported; |
| 27 return false; | |
| 28 } | |
| 29 | |
| 30 for (auto device : simulated_devices_) { | |
| 31 BluetoothLowEnergyDeviceInfo* device_info = | |
| 32 new BluetoothLowEnergyDeviceInfo(); | |
| 33 *device_info = *(device.second->device_info); | |
| 34 devices->push_back(device_info); | |
| 35 } | |
| 36 return true; | |
| 18 } | 37 } |
| 19 | 38 |
| 20 bool BluetoothLowEnergyWrapperFake:: | 39 bool BluetoothLowEnergyWrapperFake:: |
| 21 EnumerateKnownBluetoothLowEnergyGattServiceDevices( | 40 EnumerateKnownBluetoothLowEnergyGattServiceDevices( |
| 22 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, | 41 ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
| 23 std::string* error) { | 42 std::string* error) { |
| 24 NOTIMPLEMENTED(); | 43 if (!IsBluetoothLowEnergySupported()) { |
| 25 return false; | 44 *error = kPlatformNotSupported; |
| 45 return false; | |
| 46 } | |
| 47 | |
| 48 for (auto device : simulated_devices_) { | |
| 49 for (auto service : device.second->primary_services) { | |
| 50 BluetoothLowEnergyDeviceInfo* device_info = | |
| 51 new BluetoothLowEnergyDeviceInfo(); | |
| 52 *device_info = *(device.second->device_info); | |
| 53 // Fake file path of a GATT service device is | |
| 54 // "device_file_path/service_attribute_handle". | |
| 55 base::string16 path = | |
| 56 device.second->device_info->path.value() + L"/" + | |
| 57 std::to_wstring(service.second->service_info->AttributeHandle); | |
| 58 device_info->path = base::FilePath(path); | |
| 59 devices->push_back(device_info); | |
| 60 } | |
| 61 } | |
| 62 return true; | |
| 26 } | 63 } |
| 27 | 64 |
| 28 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( | 65 bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( |
| 29 const base::FilePath& device_path, | 66 const base::FilePath& device_path, |
| 30 ScopedVector<BluetoothLowEnergyServiceInfo>* services, | 67 ScopedVector<BluetoothLowEnergyServiceInfo>* services, |
| 31 std::string* error) { | 68 std::string* error) { |
| 32 NOTIMPLEMENTED(); | 69 if (!IsBluetoothLowEnergySupported()) { |
| 33 return false; | 70 *error = kPlatformNotSupported; |
| 71 return false; | |
| 72 } | |
| 73 | |
| 74 base::string16 device_address; | |
| 75 base::string16 service_attribute_handle; | |
| 76 base::string16 path = device_path.value(); | |
| 77 std::size_t found = path.find('/'); | |
|
scheib
2016/02/07 02:24:08
Comment to reference above the expected format of
gogerald1
2016/02/08 19:23:50
Done.
| |
| 78 if (found != base::string16::npos) { | |
| 79 device_address = path.substr(0, found - 1); | |
| 80 service_attribute_handle = path.substr(found + 1); | |
| 81 } else { | |
| 82 device_address = path; | |
| 83 } | |
| 84 | |
| 85 BLEDevicesMap::iterator it_d = simulated_devices_.find( | |
| 86 std::string(device_address.begin(), device_address.end())); | |
| 87 CHECK(it_d != simulated_devices_.end()); | |
| 88 | |
| 89 if (!service_attribute_handle.empty()) { | |
|
scheib
2016/02/07 02:24:08
Comment explaining what's going on when no service
gogerald1
2016/02/08 19:23:50
Done.
| |
| 90 BLEGattServicesMap::iterator it_s = | |
| 91 it_d->second->primary_services.find(std::string( | |
| 92 service_attribute_handle.begin(), service_attribute_handle.end())); | |
| 93 CHECK(it_s != it_d->second->primary_services.end()); | |
| 94 BluetoothLowEnergyServiceInfo* service_info = | |
| 95 new BluetoothLowEnergyServiceInfo(); | |
| 96 service_info->uuid = it_s->second->service_info->ServiceUuid; | |
| 97 service_info->attribute_handle = | |
| 98 it_s->second->service_info->AttributeHandle; | |
| 99 services->push_back(service_info); | |
| 100 } else { | |
| 101 for (auto primary_service : it_d->second->primary_services) { | |
| 102 BluetoothLowEnergyServiceInfo* service_info = | |
| 103 new BluetoothLowEnergyServiceInfo(); | |
| 104 service_info->uuid = primary_service.second->service_info->ServiceUuid; | |
| 105 service_info->attribute_handle = | |
| 106 primary_service.second->service_info->AttributeHandle; | |
| 107 services->push_back(service_info); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 return true; | |
| 112 } | |
| 113 | |
| 114 BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( | |
| 115 std::string device_name, | |
| 116 BLUETOOTH_ADDRESS device_address) { | |
| 117 BLEDevice* device = new BLEDevice(); | |
| 118 BluetoothLowEnergyDeviceInfo* device_info = | |
| 119 new BluetoothLowEnergyDeviceInfo(); | |
| 120 // Use string of device address as fake file path of the device. | |
| 121 std::string string_device_address = | |
| 122 BluetoothAddressToCanonicalString(device_address); | |
| 123 device_info->path = base::FilePath(base::string16( | |
| 124 string_device_address.begin(), string_device_address.end())); | |
| 125 device_info->friendly_name = device_name; | |
| 126 device_info->address = device_address; | |
| 127 device->device_info.reset(device_info); | |
| 128 simulated_devices_.set(string_device_address, scoped_ptr<BLEDevice>(device)); | |
| 129 return device; | |
| 130 } | |
| 131 | |
| 132 BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( | |
| 133 BLEDevice* device, | |
| 134 std::string uuid) { | |
| 135 CHECK(device); | |
| 136 | |
| 137 BLEGattService* service = new BLEGattService(); | |
| 138 PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; | |
| 139 std::string string_device_address = | |
| 140 BluetoothAddressToCanonicalString(device->device_info->address); | |
| 141 service_info->AttributeHandle = | |
| 142 GenerateAnUniqueAttributeHandle(string_device_address); | |
| 143 service_info->ServiceUuid = CanonicalStringToBTH_LE_UUID(uuid); | |
| 144 service->service_info.reset(service_info); | |
| 145 device->primary_services.set(std::to_string(service_info->AttributeHandle), | |
| 146 scoped_ptr<BLEGattService>(service)); | |
| 147 return service; | |
| 148 } | |
| 149 | |
| 150 USHORT BluetoothLowEnergyWrapperFake::GenerateAnUniqueAttributeHandle( | |
| 151 std::string device_address) { | |
| 152 BLEAttributeHandleTable::iterator it = | |
| 153 attribute_handle_table_.find(device_address); | |
| 154 if (it != attribute_handle_table_.end()) { | |
| 155 USHORT max_attribute_handle = *(it->second->rbegin()); | |
|
scheib
2016/02/07 02:24:08
it->second is reference a few times in this method
gogerald1
2016/02/08 19:23:51
It seems base::ScopedPtrHashMap does not implement
| |
| 156 if (max_attribute_handle < 0xFFFF) { | |
| 157 USHORT new_attribute_handle = max_attribute_handle + 1; | |
| 158 it->second->insert(new_attribute_handle); | |
| 159 return new_attribute_handle; | |
| 160 } else { | |
| 161 USHORT i = 1; | |
| 162 for (; i < 0xFFFF; i++) { | |
| 163 if (it->second->find(i) == it->second->end()) | |
| 164 break; | |
| 165 } | |
| 166 if (i >= 0xFFFF) | |
| 167 return 0; | |
| 168 it->second->insert(i); | |
| 169 return i; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 USHORT smallest_att_handle = 1; | |
| 174 std::set<USHORT>* new_set = new std::set<USHORT>(); | |
| 175 new_set->insert(smallest_att_handle); | |
| 176 attribute_handle_table_.set(device_address, | |
| 177 scoped_ptr<std::set<USHORT>>(new_set)); | |
| 178 return smallest_att_handle; | |
| 179 } | |
| 180 | |
| 181 BTH_LE_UUID BluetoothLowEnergyWrapperFake::CanonicalStringToBTH_LE_UUID( | |
| 182 std::string uuid) { | |
| 183 BTH_LE_UUID win_uuid; | |
| 184 win_uuid.IsShortUuid = true; | |
| 185 unsigned int data[1]; | |
| 186 int result = sscanf_s(uuid.c_str(), "%04x", &data[0]); | |
|
scheib
2016/02/07 02:24:08
The device::BluetoothUUID.value() isn't always 4 h
gogerald1
2016/02/08 19:23:50
Yes.
gogerald1
2016/02/08 19:23:50
Done.
| |
| 187 CHECK(result == 1); | |
| 188 win_uuid.Value.ShortUuid = data[0]; | |
| 189 return win_uuid; | |
| 190 } | |
| 191 | |
| 192 std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString( | |
| 193 const BLUETOOTH_ADDRESS& btha) { | |
| 194 std::string result = base::StringPrintf( | |
| 195 "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4], | |
| 196 btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]); | |
| 197 return result; | |
| 34 } | 198 } |
| 35 | 199 |
| 36 } // namespace win | 200 } // namespace win |
| 37 } // namespace device | 201 } // namespace device |
| OLD | NEW |