pw_bluetooth_proxy: Add some emboss helper functions
Bug: 326499611
Test: CQ
Change-Id: Ifc1af4f0e139fe3f5ff7f55fcf5c3b51d78ef64a
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/205741
Pigweed-Auto-Submit: David Rees <drees@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Reviewed-by: Ben Lawson <benlawson@google.com>
diff --git a/pw_bluetooth_proxy/BUILD.bazel b/pw_bluetooth_proxy/BUILD.bazel
index fa5a4b2..63b28eb 100644
--- a/pw_bluetooth_proxy/BUILD.bazel
+++ b/pw_bluetooth_proxy/BUILD.bazel
@@ -21,6 +21,8 @@
filegroup(
name = "files_not_in_bazel_yet",
srcs = [
+ "emboss_util.h",
+ "emboss_util_test.cc",
"hci_proxy.cc",
"passthrough_test.cc",
"public/pw_bluetooth_proxy/common.h",
diff --git a/pw_bluetooth_proxy/BUILD.gn b/pw_bluetooth_proxy/BUILD.gn
index 5cf8abf..30db653 100644
--- a/pw_bluetooth_proxy/BUILD.gn
+++ b/pw_bluetooth_proxy/BUILD.gn
@@ -34,7 +34,10 @@
}
pw_test_group("tests") {
- tests = [ ":proxy_passthrough_test" ]
+ tests = [
+ ":pw_bluetooth_proxy_test",
+ ":emboss_util_test",
+ ]
}
pw_source_set("pw_bluetooth_proxy") {
@@ -53,10 +56,29 @@
sources = [ "hci_proxy.cc" ]
}
-pw_test("proxy_passthrough_test") {
+pw_test("emboss_util_test") {
enable_if =
dir_pw_third_party_emboss != "" && pw_chrono_SYSTEM_CLOCK_BACKEND != ""
- sources = [ "passthrough_test.cc" ]
+ sources = [
+ "emboss_util.h",
+ "emboss_util_test.cc",
+ ]
+ include_dirs = [ "." ]
+ deps = [
+ ":pw_bluetooth_proxy",
+ "//pw_bluetooth:emboss_hci_test",
+ "//pw_span",
+ ]
+}
+
+pw_test("pw_bluetooth_proxy_test") {
+ enable_if =
+ dir_pw_third_party_emboss != "" && pw_chrono_SYSTEM_CLOCK_BACKEND != ""
+ sources = [
+ "emboss_util.h",
+ "passthrough_test.cc",
+ ]
+ include_dirs = [ "." ]
deps = [
":pw_bluetooth_proxy",
"$dir_pw_third_party/fuchsia:stdcompat",
diff --git a/pw_bluetooth_proxy/emboss_util.h b/pw_bluetooth_proxy/emboss_util.h
new file mode 100644
index 0000000..ebc3207
--- /dev/null
+++ b/pw_bluetooth_proxy/emboss_util.h
@@ -0,0 +1,39 @@
+// 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.
+#pragma once
+
+#include <type_traits>
+
+#include "pw_span/span.h"
+
+/// Creates a pw::span on the HCI portion of an H4 buffer.
+template <typename C>
+constexpr inline auto H4HciSubspan(C&& container) {
+ return pw::span(container.data() + 1, container.size() - 1);
+}
+
+// Create an Emboss View or Writer from a pw::span value or reference. The
+// Emboss type is determined by the template's first parameter.
+// Unlike the Emboss `Make*View` creation methods, this function accepts a
+// reference so it can be used with rvalues. This is ok to do with pw::span
+// since it doesn't own its underlying data. Another key difference is the
+// caller explicitly chooses if they want a View or a Writer using the first
+// template argument.
+template <
+ typename EmbossT,
+ typename ContainerT,
+ typename = std::enable_if<std::is_base_of_v<pw::span<uint8_t>, ContainerT>>>
+constexpr inline EmbossT MakeEmboss(ContainerT&& buffer) {
+ return EmbossT(buffer.data(), buffer.size());
+}
diff --git a/pw_bluetooth_proxy/emboss_util_test.cc b/pw_bluetooth_proxy/emboss_util_test.cc
new file mode 100644
index 0000000..a57b4f1
--- /dev/null
+++ b/pw_bluetooth_proxy/emboss_util_test.cc
@@ -0,0 +1,62 @@
+// 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 "emboss_util.h"
+
+#include "pw_bluetooth/hci_test.emb.h"
+#include "pw_unit_test/framework.h" // IWYU pragma: keep
+
+namespace pw::bluetooth::proxy {
+namespace {
+
+TEST(EmbossUtilTest, CreateH4Subspan) {
+ std::array<uint8_t, 4> buffer = {0x00, 0x01, 0x02, 0x03};
+ auto span = H4HciSubspan(buffer);
+ EXPECT_EQ(span.front(), buffer[1]);
+ EXPECT_EQ(span.back(), buffer[3]);
+ EXPECT_EQ(span.size(), buffer.size() - 1);
+}
+
+TEST(EmbossUtilTest, MakeViewFromSpan) {
+ std::array<uint8_t, 4> buffer = {0x00, 0x01, 0x02, 0x03};
+ auto span = pw::span(buffer);
+ auto view = MakeEmboss<emboss::TestCommandPacketView>(span);
+ EXPECT_TRUE(view.IsComplete());
+ EXPECT_EQ(view.payload().Read(), 0x03);
+}
+
+TEST(EmbossUtilTest, MakeWriterFromSpan) {
+ std::array<uint8_t, 4> buffer = {0x00, 0x01, 0x02, 0x03};
+ auto span = pw::span(buffer);
+ auto view = MakeEmboss<emboss::TestCommandPacketWriter>(span);
+ EXPECT_TRUE(view.IsComplete());
+ EXPECT_EQ(view.payload().Read(), 0x03);
+}
+
+TEST(EmbossUtilTest, MakeViewFromSubspan) {
+ std::array<uint8_t, 5> buffer = {0x00, 0x01, 0x02, 0x03, 0x04};
+ auto view = MakeEmboss<emboss::TestCommandPacketView>(H4HciSubspan(buffer));
+ EXPECT_TRUE(view.IsComplete());
+ EXPECT_EQ(view.payload().Read(), 0x04);
+}
+
+TEST(EmbossUtilTest, MakeWriterFromSubspan) {
+ std::array<uint8_t, 5> buffer = {0x00, 0x01, 0x02, 0x03, 0x04};
+ auto view = MakeEmboss<emboss::TestCommandPacketWriter>(H4HciSubspan(buffer));
+ EXPECT_TRUE(view.IsComplete());
+ EXPECT_EQ(view.payload().Read(), 0x04);
+}
+
+} // namespace
+} // namespace pw::bluetooth::proxy
diff --git a/pw_bluetooth_proxy/passthrough_test.cc b/pw_bluetooth_proxy/passthrough_test.cc
index 2ce8abd..80e1466 100644
--- a/pw_bluetooth_proxy/passthrough_test.cc
+++ b/pw_bluetooth_proxy/passthrough_test.cc
@@ -15,6 +15,7 @@
#include <cstdint>
#include <numeric>
+#include "emboss_util.h"
#include "lib/stdcompat/utility.h"
#include "pw_bluetooth/hci_commands.emb.h"
#include "pw_bluetooth/hci_common.emb.h"
@@ -30,12 +31,6 @@
// Util functions
-// Create pw::span on the HCI portion of an H4 buffer.
-template <typename C>
-constexpr const pw::span<uint8_t> HciSubspanOfH4Buffer(C&& container) {
- return pw::span(container.data() + 1, container.size() - 1);
-}
-
// Simple struct for returning a H4 array and an emboss view on its HCI packet.
template <typename EmbossT>
struct EmbossViewWithH4Buffer {
@@ -52,8 +47,7 @@
EmbossViewWithH4Buffer<EmbossT> view_arr;
std::iota(view_arr.arr.begin(), view_arr.arr.end(), 100);
view_arr.arr[0] = cpp23::to_underlying(emboss::H4PacketType::COMMAND);
- const auto hci_span = HciSubspanOfH4Buffer(view_arr.arr);
- view_arr.view = EmbossT(&hci_span);
+ view_arr.view = MakeEmboss<EmbossT>(H4HciSubspan(view_arr.arr));
EXPECT_TRUE(view_arr.view.IsComplete());
view_arr.view.header().opcode_full().Write(opcode);
return view_arr;
@@ -77,8 +71,7 @@
EmbossViewWithH4Buffer<EmbossT> view_arr;
std::iota(view_arr.arr.begin(), view_arr.arr.end(), 100);
view_arr.arr[0] = cpp23::to_underlying(emboss::H4PacketType::EVENT);
- const auto hci_span = HciSubspanOfH4Buffer(view_arr.arr);
- view_arr.view = EmbossT(&hci_span);
+ view_arr.view = MakeEmboss<EmbossT>(H4HciSubspan(view_arr.arr));
view_arr.view.header().event_code().Write(event_code);
view_arr.view.status().Write(status_code);
EXPECT_TRUE(view_arr.view.IsComplete());