Skip to content

Commit

Permalink
pw_bluetooth_proxy: Separate rx_additional_credits method
Browse files Browse the repository at this point in the history
Decouple L2CAP CoC acquisition & sending of additional credits.

Fixed: 380076024
Change-Id: Ia2f7ce093598d08e1f61d246832d1105cae16ef2
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/252352
Docs-Not-Needed: Ali Saeed <[email protected]>
Commit-Queue: Ali Saeed <[email protected]>
Lint: Lint 🤖 <[email protected]>
Reviewed-by: David Rees <[email protected]>
  • Loading branch information
acsaeed authored and CQ Bot Account committed Dec 6, 2024
1 parent 22ec962 commit ffb5324
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 41 deletions.
30 changes: 16 additions & 14 deletions pw_bluetooth_proxy/proxy_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -399,26 +399,14 @@ pw::Result<L2capCoc> ProxyHost::AcquireL2capCoc(
L2capCoc::CocConfig tx_config,
Function<void(pw::span<uint8_t> payload)>&& receive_fn,
Function<void(L2capCoc::Event event)>&& event_fn,
Function<void()>&& queue_space_available_fn,
uint16_t rx_additional_credits) {
Function<void()>&& queue_space_available_fn) {
Status status = acl_data_channel_.CreateAclConnection(connection_handle,
AclTransportType::kLe);
if (status.IsResourceExhausted()) {
return pw::Status::Unavailable();
}
PW_CHECK(status.ok() || status.IsAlreadyExists());
if (rx_additional_credits > 0) {
L2capSignalingChannel* signaling_channel =
acl_data_channel_.FindSignalingChannel(
connection_handle,
static_cast<uint16_t>(emboss::L2capFixedCid::LE_U_SIGNALING));
PW_CHECK(signaling_channel);
status = signaling_channel->SendFlowControlCreditInd(rx_config.cid,
rx_additional_credits);
if (!status.ok()) {
return status;
}
}

return L2capCocInternal::Create(l2cap_channel_manager_,
connection_handle,
rx_config,
Expand All @@ -428,6 +416,20 @@ pw::Result<L2capCoc> ProxyHost::AcquireL2capCoc(
std::move(queue_space_available_fn));
}

pw::Status ProxyHost::SendAdditionalRxCredits(uint16_t connection_handle,
uint16_t local_cid,
uint16_t additional_rx_credits) {
L2capSignalingChannel* signaling_channel =
acl_data_channel_.FindSignalingChannel(
connection_handle,
static_cast<uint16_t>(emboss::L2capFixedCid::LE_U_SIGNALING));
if (!signaling_channel) {
return Status::NotFound();
}
return signaling_channel->SendFlowControlCreditInd(local_cid,
additional_rx_credits);
}

pw::Result<BasicL2capChannel> ProxyHost::AcquireBasicL2capChannel(
uint16_t connection_handle,
uint16_t local_cid,
Expand Down
14 changes: 8 additions & 6 deletions pw_bluetooth_proxy/proxy_host_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3965,7 +3965,7 @@ TEST(L2capSignalingTest, CreditIndAddressedToNonManagedChannelForwardedToHost) {
EXPECT_EQ(forwards_to_host, 1);
}

TEST(L2capSignalingTest, RxAdditionalCreditsSentOnL2capCocAcquisition) {
TEST(L2capSignalingTest, RxAdditionalCreditsSent) {
struct {
uint16_t handle = 123;
uint16_t local_cid = 456;
Expand Down Expand Up @@ -4014,11 +4014,13 @@ TEST(L2capSignalingTest, RxAdditionalCreditsSentOnL2capCocAcquisition) {
// Allow proxy to reserve 1 LE credit.
PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));

L2capCoc channel =
BuildCoc(proxy,
CocParameters{.handle = capture.handle,
.local_cid = capture.local_cid,
.rx_additional_credits = capture.credits});
// Build channel so ACL connection is registered.
L2capCoc channel = BuildCoc(
proxy,
CocParameters{.handle = capture.handle, .local_cid = capture.local_cid});

PW_TEST_EXPECT_OK(proxy.SendAdditionalRxCredits(
capture.handle, capture.local_cid, capture.credits));

EXPECT_EQ(capture.sends_called, 1);
}
Expand Down
53 changes: 35 additions & 18 deletions pw_bluetooth_proxy/public/pw_bluetooth_proxy/proxy_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,22 @@ class ProxyHost {
/// Returns an L2CAP connection-oriented channel that supports writing to and
/// reading from a remote peer.
///
/// @param[in] connection_handle The connection handle of the remote peer.
/// @param[in] connection_handle The connection handle of the remote peer.
///
/// @param[in] rx_config Parameters applying to reading packets.
/// See `l2cap_coc.h` for details.
/// @param[in] rx_config Parameters applying to reading packets. See
/// `l2cap_coc.h` for details.
///
/// @param[in] tx_config Parameters applying to writing packets.
/// See `l2cap_coc.h` for details.
/// @param[in] tx_config Parameters applying to writing packets. See
/// `l2cap_coc.h` for details.
///
/// @param[in] receive_fn Read callback to be invoked on Rx SDUs.
/// @param[in] receive_fn Read callback to be invoked on Rx SDUs.
///
/// @param[in] event_fn Handle asynchronous events such as errors
/// encountered by the channel.
///
/// @param[in] rx_additional_credits Send L2CAP_FLOW_CONTROL_CREDIT_IND to
/// dispense remote peer additional credits
/// for this channel.
/// @param[in] event_fn Handle asynchronous events such as errors
/// encountered by the channel.
///
/// @param[in] queue_space_available_fn
/// Callback to be invoked after resources become
/// available after an UNAVAILABLE Write.
/// Callback to be invoked after resources
/// become available after an UNAVAILABLE Write.
///
/// @returns @rst
///
Expand All @@ -147,10 +143,31 @@ class ProxyHost {
uint16_t connection_handle,
L2capCoc::CocConfig rx_config,
L2capCoc::CocConfig tx_config,
Function<void(pw::span<uint8_t> payload)>&& receive_fn,
Function<void(L2capCoc::Event event)>&& event_fn,
Function<void()>&& queue_space_available_fn = nullptr,
uint16_t rx_additional_credits = 0);
pw::Function<void(pw::span<uint8_t> payload)>&& receive_fn,
pw::Function<void(L2capCoc::Event event)>&& event_fn,
Function<void()>&& queue_space_available_fn = nullptr);

/// Send an L2CAP_FLOW_CONTROL_CREDIT_IND signaling packet to dispense the
/// remote peer additional L2CAP connection-oriented channel credits for this
/// channel.
///
/// @param[in] connection_handle ACL connection over which this L2CAP
/// connection-oriented channel exists.
///
/// @param[in] local_cid L2CAP channel ID of local endpoint.
///
/// @param[in] additional_rx_credits Number of credits to dispense.
///
/// @returns @rst
///
/// .. pw-status-codes::
/// INVALID_ARGUMENT: CID invalid (check logs).
/// NOT_FOUND: Requested ACL connection does not exist.
/// UNAVAILABLE: Send could not be queued right now (transient error).
/// @endrst
pw::Status SendAdditionalRxCredits(uint16_t connection_handle,
uint16_t local_cid,
uint16_t additional_rx_credits);

/// Returns an L2CAP channel operating in basic mode that supports writing to
/// and reading from a remote peer.
Expand Down
2 changes: 1 addition & 1 deletion pw_bluetooth_proxy/pw_bluetooth_proxy_private/test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ struct CocParameters {
uint16_t tx_credits = 1;
pw::Function<void(pw::span<uint8_t> payload)>&& receive_fn = nullptr;
pw::Function<void(L2capCoc::Event event)>&& event_fn = nullptr;
uint16_t rx_additional_credits = 0;
pw::Function<void()>&& queue_space_available_fn = nullptr;
};

// Open and return an L2CAP connection-oriented channel managed by `proxy`.
Expand Down
3 changes: 1 addition & 2 deletions pw_bluetooth_proxy/test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,7 @@ L2capCoc BuildCoc(ProxyHost& proxy, CocParameters params) {
.credits = params.tx_credits},
std::move(params.receive_fn),
std::move(params.event_fn),
/*queue_space_available_fn=*/nullptr,
params.rx_additional_credits);
std::move(params.queue_space_available_fn));
return std::move(channel.value());
}

Expand Down

0 comments on commit ffb5324

Please sign in to comment.