Index: device/bluetooth/bluetooth_low_energy_win_fake.cc |
diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.cc b/device/bluetooth/bluetooth_low_energy_win_fake.cc |
index d1ef1df5148e3d248fe2b29ba8e0337248f6b25a..60926be75d59020f1a15f408d0f11628227fa153 100644 |
--- a/device/bluetooth/bluetooth_low_energy_win_fake.cc |
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.cc |
@@ -4,6 +4,13 @@ |
#include "device/bluetooth/bluetooth_low_energy_win_fake.h" |
+#include "base/strings/stringprintf.h" |
+ |
+namespace { |
+const char kPlatformNotSupported[] = |
+ "Bluetooth Low energy is only supported on Windows 8 and later."; |
+} // namespace |
+ |
namespace device { |
namespace win { |
@@ -13,24 +20,207 @@ BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} |
bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices( |
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
std::string* error) { |
- NOTIMPLEMENTED(); |
- return false; |
+ if (!IsBluetoothLowEnergySupported()) { |
+ *error = kPlatformNotSupported; |
+ return false; |
+ } |
+ |
+ for (auto& device : simulated_devices_) { |
+ BluetoothLowEnergyDeviceInfo* device_info = |
+ new BluetoothLowEnergyDeviceInfo(); |
+ *device_info = *(device.second->device_info); |
+ devices->push_back(device_info); |
+ } |
+ return true; |
} |
bool BluetoothLowEnergyWrapperFake:: |
EnumerateKnownBluetoothLowEnergyGattServiceDevices( |
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
std::string* error) { |
- NOTIMPLEMENTED(); |
- return false; |
+ if (!IsBluetoothLowEnergySupported()) { |
+ *error = kPlatformNotSupported; |
+ return false; |
+ } |
+ |
+ for (auto& device : simulated_devices_) { |
+ for (auto& service : device.second->primary_services) { |
+ BluetoothLowEnergyDeviceInfo* device_info = |
+ new BluetoothLowEnergyDeviceInfo(); |
+ *device_info = *(device.second->device_info); |
+ base::string16 path = GenerateBLEGattServiceDevicePath( |
+ device.second->device_info->path.value(), |
+ service.second->service_info->AttributeHandle); |
+ device_info->path = base::FilePath(path); |
+ devices->push_back(device_info); |
+ } |
+ } |
+ return true; |
} |
bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( |
const base::FilePath& device_path, |
ScopedVector<BluetoothLowEnergyServiceInfo>* services, |
std::string* error) { |
- NOTIMPLEMENTED(); |
- return false; |
+ if (!IsBluetoothLowEnergySupported()) { |
+ *error = kPlatformNotSupported; |
+ return false; |
+ } |
+ |
+ base::string16 device_address = |
+ ExtractDeviceAddressFromDevicePath(device_path.value()); |
+ base::string16 service_attribute_handle = |
+ ExtractServiceAttributeHandleFromDevicePath(device_path.value()); |
+ |
+ BLEDevicesMap::iterator it_d = simulated_devices_.find( |
+ std::string(device_address.begin(), device_address.end())); |
+ CHECK(it_d != simulated_devices_.end()); |
+ |
+ // |service_attribute_handle| is empty means |device_path| is a BLE device |
+ // path, otherwise it is a BLE GATT service device path. |
+ if (service_attribute_handle.empty()) { |
+ // Return all primary services for BLE device. |
+ for (auto& primary_service : it_d->second->primary_services) { |
+ BluetoothLowEnergyServiceInfo* service_info = |
+ new BluetoothLowEnergyServiceInfo(); |
+ service_info->uuid = primary_service.second->service_info->ServiceUuid; |
+ service_info->attribute_handle = |
+ primary_service.second->service_info->AttributeHandle; |
+ services->push_back(service_info); |
+ } |
+ } else { |
+ // Return corresponding GATT service for BLE GATT service device. |
+ BLEGattServicesMap::iterator it_s = |
+ it_d->second->primary_services.find(std::string( |
+ service_attribute_handle.begin(), service_attribute_handle.end())); |
+ CHECK(it_s != it_d->second->primary_services.end()); |
+ BluetoothLowEnergyServiceInfo* service_info = |
+ new BluetoothLowEnergyServiceInfo(); |
+ service_info->uuid = it_s->second->service_info->ServiceUuid; |
+ service_info->attribute_handle = |
+ it_s->second->service_info->AttributeHandle; |
+ services->push_back(service_info); |
+ } |
+ |
+ return true; |
+} |
+ |
+BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( |
+ std::string device_name, |
+ BLUETOOTH_ADDRESS device_address) { |
+ BLEDevice* device = new BLEDevice(); |
+ BluetoothLowEnergyDeviceInfo* device_info = |
+ new BluetoothLowEnergyDeviceInfo(); |
+ std::string string_device_address = |
+ BluetoothAddressToCanonicalString(device_address); |
+ device_info->path = |
+ base::FilePath(GenerateBLEDevicePath(string_device_address)); |
+ device_info->friendly_name = device_name; |
+ device_info->address = device_address; |
+ device->device_info.reset(device_info); |
+ simulated_devices_[string_device_address] = make_scoped_ptr(device); |
+ return device; |
+} |
+ |
+BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( |
+ BLEDevice* device, |
+ std::string uuid) { |
+ CHECK(device); |
+ |
+ BLEGattService* service = new BLEGattService(); |
+ PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; |
+ std::string string_device_address = |
+ BluetoothAddressToCanonicalString(device->device_info->address); |
+ service_info->AttributeHandle = |
+ GenerateAUniqueAttributeHandle(string_device_address); |
+ service_info->ServiceUuid = CanonicalStringToBTH_LE_UUID(uuid); |
+ service->service_info.reset(service_info); |
+ device->primary_services[std::to_string(service_info->AttributeHandle)] = |
+ make_scoped_ptr(service); |
+ return service; |
+} |
+ |
+USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle( |
+ std::string device_address) { |
+ scoped_ptr<std::set<USHORT>>& set_of_ushort = |
+ attribute_handle_table_[device_address]; |
+ if (set_of_ushort) { |
+ USHORT max_attribute_handle = *set_of_ushort->rbegin(); |
+ if (max_attribute_handle < 0xFFFF) { |
+ USHORT new_attribute_handle = max_attribute_handle + 1; |
+ set_of_ushort->insert(new_attribute_handle); |
+ return new_attribute_handle; |
+ } else { |
+ USHORT i = 1; |
+ for (; i < 0xFFFF; i++) { |
+ if (set_of_ushort->find(i) == set_of_ushort->end()) |
+ break; |
+ } |
+ if (i >= 0xFFFF) |
+ return 0; |
+ set_of_ushort->insert(i); |
+ return i; |
+ } |
+ } |
+ |
+ USHORT smallest_att_handle = 1; |
+ std::set<USHORT>* new_set = new std::set<USHORT>(); |
+ new_set->insert(smallest_att_handle); |
+ set_of_ushort.reset(new_set); |
+ return smallest_att_handle; |
+} |
+ |
+base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEDevicePath( |
+ std::string device_address) { |
+ return base::string16(device_address.begin(), device_address.end()); |
+} |
+ |
+base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEGattServiceDevicePath( |
+ base::string16 resident_device_path, |
+ USHORT service_attribute_handle) { |
+ std::string sub_path = std::to_string(service_attribute_handle); |
+ return resident_device_path + L"/" + |
+ base::string16(sub_path.begin(), sub_path.end()); |
+} |
+ |
+base::string16 |
+BluetoothLowEnergyWrapperFake::ExtractDeviceAddressFromDevicePath( |
+ base::string16 path) { |
+ std::size_t found = path.find('/'); |
+ if (found != base::string16::npos) { |
+ return path.substr(0, found - 1); |
+ } |
+ return path; |
+} |
+ |
+base::string16 |
+BluetoothLowEnergyWrapperFake::ExtractServiceAttributeHandleFromDevicePath( |
+ base::string16 path) { |
+ std::size_t found = path.find('/'); |
+ if (found == base::string16::npos) |
+ return base::string16(); |
+ return path.substr(found + 1); |
+} |
+ |
+BTH_LE_UUID BluetoothLowEnergyWrapperFake::CanonicalStringToBTH_LE_UUID( |
+ std::string uuid) { |
+ BTH_LE_UUID win_uuid; |
+ // Only short UUIDs (4 hex digits) have beened used in BluetoothTest right |
+ // now. Need fix after using long UUIDs. |
+ win_uuid.IsShortUuid = true; |
+ unsigned int data[1]; |
+ int result = sscanf_s(uuid.c_str(), "%04x", &data[0]); |
+ CHECK(result == 1); |
+ win_uuid.Value.ShortUuid = data[0]; |
+ return win_uuid; |
+} |
+ |
+std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString( |
+ const BLUETOOTH_ADDRESS& btha) { |
+ std::string result = base::StringPrintf( |
+ "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4], |
+ btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]); |
+ return result; |
} |
} // namespace win |