| 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 548286d3a2335deda27fa714774a568b128feae5..b81a319c48eb7330b095bac1af7c29d739d99125 100644
|
| --- a/device/bluetooth/bluetooth_low_energy_win_fake.cc
|
| +++ b/device/bluetooth/bluetooth_low_energy_win_fake.cc
|
| @@ -27,6 +27,9 @@ GattCharacteristic::~GattCharacteristic() {}
|
| GattDescriptor::GattDescriptor() {}
|
| GattDescriptor::~GattDescriptor() {}
|
|
|
| +GattServiceObserver::GattServiceObserver() {}
|
| +GattServiceObserver::~GattServiceObserver() {}
|
| +
|
| BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake()
|
| : observer_(nullptr) {}
|
| BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {}
|
| @@ -232,7 +235,87 @@ HRESULT BluetoothLowEnergyWrapperFake::WriteCharacteristicValue(
|
| win_value->DataSize = new_value->DataSize;
|
| target_characteristic->value.reset(win_value);
|
| if (observer_)
|
| - observer_->onWriteGattCharacteristicValue(win_value);
|
| + observer_->OnWriteGattCharacteristicValue(win_value);
|
| + return S_OK;
|
| +}
|
| +
|
| +HRESULT BluetoothLowEnergyWrapperFake::RegisterGattEvents(
|
| + base::FilePath& service_path,
|
| + BTH_LE_GATT_EVENT_TYPE type,
|
| + PVOID event_parameter,
|
| + PFNBLUETOOTH_GATT_EVENT_CALLBACK callback,
|
| + PVOID context,
|
| + BLUETOOTH_GATT_EVENT_HANDLE* out_handle) {
|
| + base::string16 device_address =
|
| + ExtractDeviceAddressFromDevicePath(service_path.value());
|
| + BLEDevice* target_device = GetSimulatedBLEDevice(
|
| + std::string(device_address.begin(), device_address.end()));
|
| + if (target_device == nullptr)
|
| + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
|
| + const std::vector<std::string> service_att_handles =
|
| + ExtractServiceAttributeHandlesFromDevicePath(service_path.value());
|
| + GattService* target_service =
|
| + GetSimulatedGattService(target_device, service_att_handles);
|
| + if (target_service == nullptr)
|
| + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
|
| +
|
| + PBLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION parameter =
|
| + (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION)event_parameter;
|
| + for (USHORT i = 0; i < parameter->NumCharacteristics; i++) {
|
| + GattCharacteristic* target_characteristic = GetSimulatedGattCharacteristic(
|
| + target_service,
|
| + std::to_string(parameter->Characteristics[i].AttributeHandle));
|
| + CHECK(target_characteristic);
|
| +
|
| + // Return error simulated by SimulateGattCharacteristicSetNotifyError.
|
| + if (target_characteristic->notify_errors.size()) {
|
| + HRESULT error = target_characteristic->notify_errors[0];
|
| + target_characteristic->notify_errors.erase(
|
| + target_characteristic->notify_errors.begin());
|
| + return error;
|
| + }
|
| +
|
| + // Get CCC descriptor.
|
| + GattDescriptor* target_descriptor = GetCCCDescriptor(target_characteristic);
|
| + if (target_descriptor == nullptr)
|
| + return E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED;
|
| + if (observer_)
|
| + observer_->OnStartCharacteristicNotification();
|
| +
|
| + // Return error simualted by SimulateGattDescriptorWriteError.
|
| + if (target_descriptor->write_errors.size()) {
|
| + HRESULT error = target_descriptor->write_errors[0];
|
| + target_descriptor->write_errors.erase(
|
| + target_descriptor->write_errors.begin());
|
| + return error;
|
| + }
|
| +
|
| + // Write CCC descriptor.
|
| + std::vector<uint8_t> new_value;
|
| + if (target_characteristic->characteristic_info->IsNotifiable)
|
| + new_value.push_back(1);
|
| + else if (target_characteristic->characteristic_info->IsIndicatable)
|
| + new_value.push_back(2);
|
| + else
|
| + return E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED;
|
| + new_value.push_back(0);
|
| + SimulateGattDescriptorWrite(target_descriptor, new_value);
|
| + }
|
| +
|
| + scoped_ptr<GattServiceObserver> observer(new GattServiceObserver());
|
| + observer->callback = callback;
|
| + observer->context = context;
|
| + BLUETOOTH_GATT_EVENT_HANDLE handle =
|
| + (BLUETOOTH_GATT_EVENT_HANDLE)observer.get();
|
| + gatt_service_observers_[handle] = std::move(observer);
|
| + target_service->observers.push_back(handle);
|
| +
|
| + return S_OK;
|
| +}
|
| +
|
| +HRESULT BluetoothLowEnergyWrapperFake::UnregisterGattEvent(
|
| + BLUETOOTH_GATT_EVENT_HANDLE event_handle) {
|
| + gatt_service_observers_.erase(event_handle);
|
| return S_OK;
|
| }
|
|
|
| @@ -377,6 +460,27 @@ void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicValue(
|
| characteristic->value.reset(win_value);
|
| }
|
|
|
| +void BluetoothLowEnergyWrapperFake::
|
| + SimulateCharacteristicValueChangeNotification(
|
| + GattService* parent_service,
|
| + GattCharacteristic* characteristic) {
|
| + for (auto observer : parent_service->observers) {
|
| + GattServiceObserverTable::iterator it =
|
| + gatt_service_observers_.find(observer);
|
| + // Check if |observer| has been unregistered by UnregisterGattEvent.
|
| + if (it != gatt_service_observers_.end()) {
|
| + BLUETOOTH_GATT_VALUE_CHANGED_EVENT event;
|
| + event.ChangedAttributeHandle =
|
| + characteristic->characteristic_info->AttributeHandle;
|
| + event.CharacteristicValueDataSize =
|
| + characteristic->value->DataSize + (ULONG)sizeof(ULONG);
|
| + event.CharacteristicValue = characteristic->value.get();
|
| + it->second->callback(CharacteristicValueChangedEvent, &event,
|
| + it->second->context);
|
| + }
|
| + }
|
| +}
|
| +
|
| void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicReadError(
|
| GattCharacteristic* characteristic,
|
| HRESULT error) {
|
| @@ -391,6 +495,13 @@ void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicWriteError(
|
| characteristic->write_errors.push_back(error);
|
| }
|
|
|
| +void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicSetNotifyError(
|
| + GattCharacteristic* characteristic,
|
| + HRESULT error) {
|
| + CHECK(characteristic);
|
| + characteristic->notify_errors.push_back(error);
|
| +}
|
| +
|
| void BluetoothLowEnergyWrapperFake::SimulateGattDescriptor(
|
| std::string device_address,
|
| GattCharacteristic* characteristic,
|
| @@ -404,6 +515,34 @@ void BluetoothLowEnergyWrapperFake::SimulateGattDescriptor(
|
| descriptor->descriptor_info->AttributeHandle)] = std::move(descriptor);
|
| }
|
|
|
| +GattDescriptor* BluetoothLowEnergyWrapperFake::GetSimulatedDescriptor(
|
| + GattCharacteristic* parent_characteristic,
|
| + std::string attribute_handle) {
|
| + GattDescriptorsMap::const_iterator it =
|
| + parent_characteristic->included_descriptors.find(attribute_handle);
|
| + if (it != parent_characteristic->included_descriptors.end())
|
| + return it->second.get();
|
| + return nullptr;
|
| +}
|
| +
|
| +void BluetoothLowEnergyWrapperFake::SimulateGattDescriptorWrite(
|
| + GattDescriptor* descriptor,
|
| + const std::vector<uint8_t>& value) {
|
| + ULONG length = (ULONG)(sizeof(BTH_LE_GATT_DESCRIPTOR_VALUE) + value.size());
|
| + descriptor->value.reset((BTH_LE_GATT_DESCRIPTOR_VALUE*)(new UCHAR[length]));
|
| + descriptor->value->DataSize = (ULONG)value.size();
|
| + for (size_t i = 0; i < value.size(); i++)
|
| + descriptor->value->Data[i] = value[i];
|
| + if (observer_)
|
| + observer_->OnWriteGattDescriptorValue(descriptor->value.get());
|
| +}
|
| +
|
| +void BluetoothLowEnergyWrapperFake::SimulateGattDescriptorWriteError(
|
| + GattDescriptor* descriptor,
|
| + HRESULT error) {
|
| + descriptor->write_errors.push_back(error);
|
| +}
|
| +
|
| void BluetoothLowEnergyWrapperFake::AddObserver(Observer* observer) {
|
| observer_ = observer;
|
| }
|
| @@ -513,5 +652,29 @@ std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString(
|
| return result;
|
| }
|
|
|
| +GattDescriptor* BluetoothLowEnergyWrapperFake::GetCCCDescriptor(
|
| + GattCharacteristic* characteristic) {
|
| + for (const auto& d : characteristic->included_descriptors) {
|
| + const BTH_LE_UUID* uuid = &(d.second->descriptor_info->DescriptorUuid);
|
| + if (uuid->IsShortUuid)
|
| + continue;
|
| +
|
| + std::string uuid_string = base::StringPrintf(
|
| + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
| + uuid->Value.LongUuid.Data1, uuid->Value.LongUuid.Data2,
|
| + uuid->Value.LongUuid.Data3, uuid->Value.LongUuid.Data4[0],
|
| + uuid->Value.LongUuid.Data4[1], uuid->Value.LongUuid.Data4[2],
|
| + uuid->Value.LongUuid.Data4[3], uuid->Value.LongUuid.Data4[4],
|
| + uuid->Value.LongUuid.Data4[5], uuid->Value.LongUuid.Data4[6],
|
| + uuid->Value.LongUuid.Data4[7]);
|
| + if (uuid_string != "00002902-0000-1000-8000-00805f9b34fb")
|
| + continue;
|
| +
|
| + return d.second.get();
|
| + }
|
| +
|
| + return nullptr;
|
| +}
|
| +
|
| } // namespace win
|
| } // namespace device
|
|
|