| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "generic_access_client.h" |
| |
| #include "src/connectivity/bluetooth/core/bt-host/gap/gap.h" |
| |
| namespace bt::gap::internal { |
| |
| GenericAccessClient::GenericAccessClient(PeerId peer_id, fbl::RefPtr<gatt::RemoteService> service) |
| : service_(std::move(service)), peer_id_(peer_id), weak_ptr_factory_(this) { |
| ZX_ASSERT(service_); |
| ZX_ASSERT(service_->uuid() == kGenericAccessService); |
| } |
| |
| void GenericAccessClient::ReadPeripheralPreferredConnectionParameters( |
| ConnectionParametersCallback callback) { |
| auto self = weak_ptr_factory_.GetWeakPtr(); |
| service_->DiscoverCharacteristics([self, cb = std::move(callback)](auto status, |
| auto chars) mutable { |
| if (!self) { |
| return; |
| } |
| |
| if (!status) { |
| cb(fit::error(status)); |
| return; |
| } |
| |
| std::optional<gatt::CharacteristicHandle> conn_params_value_handle; |
| for (auto& [handle, chr] : chars) { |
| auto& data = chr.first; |
| if (data.type == kPeripheralPreferredConnectionParametersCharacteristic) { |
| conn_params_value_handle.emplace(data.value_handle); |
| break; |
| } |
| } |
| |
| if (!conn_params_value_handle) { |
| bt_log(DEBUG, "gap-le", |
| "GAP service does not have peripheral preferred connection parameters characteristic " |
| "(peer: %s)", |
| bt_str(self->peer_id_)); |
| cb(fit::error(att::Status(HostError::kNotFound))); |
| return; |
| } |
| |
| self->service_->ReadCharacteristic(*conn_params_value_handle, [self, cb = std::move(cb)]( |
| auto status, |
| auto& buffer) mutable { |
| if (!self) { |
| return; |
| } |
| |
| if (bt_is_error( |
| status, DEBUG, "gap-le", |
| "error reading peripheral preferred connection parameters characteristic (peer: %s)", |
| bt_str(self->peer_id_))) { |
| cb(fit::error(status)); |
| return; |
| } |
| |
| if (buffer.size() != sizeof(PeripheralPreferredConnectionParametersCharacteristicValue)) { |
| bt_log(DEBUG, "gap-le", |
| "peripheral preferred connection parameters characteristic has invalid value size " |
| "(peer: %s)", |
| bt_str(self->peer_id_)); |
| cb(fit::error(att::Status(HostError::kPacketMalformed))); |
| return; |
| } |
| |
| auto& char_value = |
| buffer.template As<PeripheralPreferredConnectionParametersCharacteristicValue>(); |
| hci::LEPreferredConnectionParameters params( |
| letoh16(char_value.min_interval), letoh16(char_value.max_interval), |
| letoh16(char_value.max_latency), letoh16(char_value.supervision_timeout)); |
| |
| cb(fit::ok(params)); |
| }); |
| }); |
| } |
| |
| } // namespace bt::gap::internal |