blob: c473405d5d5c4842e25b6e12e478a4baf75362e5 [file] [log] [blame]
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_bluetooth_proxy/hci_proxy.h"
#include "pw_assert/check.h" // IWYU pragma: keep
#include "pw_bluetooth_proxy/common.h"
#include "pw_bluetooth_proxy/proxy_policy.h"
#include "pw_function/function.h"
#include "pw_span/span.h"
namespace pw::bluetooth::proxy {
HciProxy::HciProxy(H4HciPacketSendFn&& send_to_host_fn,
H4HciPacketSendFn&& send_to_controller_fn,
pw::span<ProxyPolicy*> policies)
: outward_send_to_host_fn_(std::move(send_to_host_fn)),
outward_send_to_controller_fn_(std::move(send_to_controller_fn)),
policies_(std::move(policies)) {
// Currently the proxy just passes packets across the policies. So here
// we just set up `pw::Function` call chains that pass the packets to each
// policy in order.
// Set the downward call chain for handling packets from host through to
// controller.
// this::firstProcessH4HciFromHostFn_ -> policy[0]::ProcessH4HciFromHost
// policy[0]::setSendToControllerFn -> policy[0+1]::ProcessH4HciFromHost
// ...
// policy[N]::setSendToControllerFn -> this::sendToController
pw::Function<void(H4HciPacketSendFn && fn)> upper_set_process_from_host_fn =
pw::bind_member<&HciProxy::setFirstProcessH4HciFromHostFn>(this);
for (ProxyPolicy* policy : policies_) {
upper_set_process_from_host_fn(
pw::bind_member<&ProxyPolicy::ProcessH4HciFromHost>(policy));
upper_set_process_from_host_fn =
pw::bind_member<&ProxyPolicy::setSendToControllerFn>(policy);
}
upper_set_process_from_host_fn(
pw::bind_member<&HciProxy::sendToController>(this));
// Set the upward call chain for handling packets from controller through to
// host.
// this::firstProcessH4HciFromControllerFn_ ->
// policy[N]::ProcessH4HciFromController
// policy[N]::setSendToHostFn -> policy[N-1]::ProcessH4HciFromController
// ...
// policy[0]::setSendToHostFn -> this::sendToHost
pw::Function<void(H4HciPacketSendFn && fn)>
lower_set_process_from_controller_fn =
pw::bind_member<&HciProxy::setFirstProcessH4HciFromControllerFn>(
this);
for (auto ri = policies_.rend(); ri != policies_.rend(); ri--) {
auto policy = *ri;
lower_set_process_from_controller_fn(
pw::bind_member<&ProxyPolicy::ProcessH4HciFromController>(policy));
lower_set_process_from_controller_fn =
pw::bind_member<&ProxyPolicy::setSendToHostFn>(policy);
}
lower_set_process_from_controller_fn(
pw::bind_member<&HciProxy::sendToHost>(this));
}
} // namespace pw::bluetooth::proxy