Merge "Rootcanal: Add LinkLayerPackets for commands"
diff --git a/gd/Android.bp b/gd/Android.bp
index e7a389a..19eaec3 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -358,6 +358,24 @@
],
}
+genrule {
+ name: "BluetoothGeneratedPackets_python3_cc",
+ tools: [
+ "bluetooth_packetgen",
+ ],
+ cmd: "$(location bluetooth_packetgen) --include=system/bt/gd --out=$(genDir) $(in)",
+ srcs: [
+ "hci/hci_packets.pdl",
+ "l2cap/l2cap_packets.pdl",
+ "security/smp_packets.pdl",
+ ],
+ out: [
+ "hci/hci_packets_python3.cc",
+ "l2cap/l2cap_packets_python3.cc",
+ "security/smp_packets_python3.cc",
+ ],
+}
+
filegroup {
name: "BluetoothFacadeProto",
srcs: [
@@ -523,3 +541,87 @@
"l2cap/classic/cert/api.pb.cc",
],
}
+
+cc_defaults {
+ name: "bluetooth_py3_native_extension_defaults",
+ include_dirs: [
+ "external/python/cpython3/Include",
+ ],
+ target: {
+ android: {
+ include_dirs: ["external/python/cpython3/android/bionic/pyconfig"],
+ },
+ android_arm: {
+ cflags: ["-DSOABI=\"cpython-38android-arm-android-bionic\""],
+ suffix: ".cpython-38android-arm-android-bionic",
+ },
+ android_arm64: {
+ cflags: ["-DSOABI=\"cpython-38android-arm64-android-bionic\""],
+ suffix: ".cpython-38android-arm64-android-bionic",
+ },
+ android_x86: {
+ cflags: ["-DSOABI=\"cpython-38android-x86-android-bionic\""],
+ suffix: ".cpython-38android-x86-android-bionic",
+ },
+ android_x86_64: {
+ cflags: ["-DSOABI=\"cpython-38android-x86_64-android-bionic\""],
+ suffix: ".cpython-38android-x86_64-android-bionic",
+ },
+ // Regenerate include dirs with android_regen.sh
+ darwin_x86_64: {
+ include_dirs: ["external/python/cpython3/android/darwin_x86_64/pyconfig"],
+ cflags: [
+ "-Wno-deprecated-declarations",
+ "-Wno-pointer-arith",
+ "-DSOABI=\"cpython-38android-x86_64-darwin\"",
+ ],
+ suffix: ".cpython-38android-x86_64-darwin",
+ },
+ linux_bionic: {
+ // NB linux_bionic is a 'host' architecture but it uses the bionic libc like 'android'
+ // targets so use the android pyconfig.
+ include_dirs: ["external/python/cpython3/android/bionic/pyconfig"],
+ cflags: ["-DSOABI=\"cpython-38android-x86_64-linux-bionic\""],
+ suffix: ".cpython-38android-x86_64-linux-bionic",
+ },
+ linux_glibc_x86: {
+ enabled: false,
+ },
+ linux_glibc_x86_64: {
+ include_dirs: ["external/python/cpython3/android/linux_x86_64/pyconfig"],
+ cflags: ["-DSOABI=\"cpython-38android-x86_64-linux-gnu\""],
+ suffix: ".cpython-38android-x86_64-linux-gnu",
+ },
+ windows: {
+ enabled: false,
+ },
+ },
+ allow_undefined_symbols: true,
+}
+
+cc_library{
+ name: "bluetooth_packets_python3",
+ defaults: [
+ "gd_defaults",
+ "bluetooth_py3_native_extension_defaults"
+ ],
+ host_supported: true,
+ srcs: [
+ "packet/python3_module.cc",
+ "l2cap/fcs.cc",
+ ":BluetoothPacketSources",
+ ],
+ generated_headers: [
+ "BluetoothGeneratedPackets_h",
+ ],
+ generated_sources: [
+ "BluetoothGeneratedPackets_python3_cc",
+ ],
+ header_libs: [
+ "pybind11_headers",
+ ],
+ cflags: [
+ "-fexceptions",
+ ],
+ rtti: true,
+}
diff --git a/gd/packet/parser/enum_gen.cc b/gd/packet/parser/enum_gen.cc
index 50d5f81..4bd5a26 100644
--- a/gd/packet/parser/enum_gen.cc
+++ b/gd/packet/parser/enum_gen.cc
@@ -20,7 +20,7 @@
#include "util.h"
-EnumGen::EnumGen(EnumDef e) : e_(e) {}
+EnumGen::EnumGen(EnumDef e) : e_(std::move(e)) {}
void EnumGen::GenDefinition(std::ostream& stream) {
stream << "enum class ";
@@ -33,6 +33,14 @@
stream << "};\n";
}
+void EnumGen::GenDefinitionPybind11(std::ostream& stream) {
+ stream << "py::enum_<" << e_.name_ << ">(m, \"" << e_.name_ << "\")";
+ for (const auto& pair : e_.constants_) {
+ stream << ".value(\"" << pair.second << "\", " << e_.name_ << "::" << pair.second << ")";
+ }
+ stream << ";\n";
+}
+
void EnumGen::GenLogging(std::ostream& stream) {
// Print out the switch statement that converts all the constants to strings.
stream << "inline std::string " << e_.name_ << "Text(const " << e_.name_ << "& param) {";
diff --git a/gd/packet/parser/enum_gen.h b/gd/packet/parser/enum_gen.h
index f3483dd..be16559 100644
--- a/gd/packet/parser/enum_gen.h
+++ b/gd/packet/parser/enum_gen.h
@@ -27,6 +27,8 @@
void GenDefinition(std::ostream& stream);
+ void GenDefinitionPybind11(std::ostream& stream);
+
void GenLogging(std::ostream& stream);
EnumDef e_;
diff --git a/gd/packet/parser/main.cc b/gd/packet/parser/main.cc
index a53d71d..05475b6 100644
--- a/gd/packet/parser/main.cc
+++ b/gd/packet/parser/main.cc
@@ -230,6 +230,100 @@
return true;
}
+bool generate_pybind11_sources_one_file(const Declarations& decls, const std::filesystem::path& input_file,
+ const std::filesystem::path& include_dir, const std::filesystem::path& out_dir,
+ const std::string& root_namespace) {
+ auto gen_relative_path = input_file.lexically_relative(include_dir).parent_path();
+
+ auto input_filename = input_file.filename().string().substr(0, input_file.filename().string().find(".pdl"));
+ auto gen_path = out_dir / gen_relative_path;
+
+ std::filesystem::create_directories(gen_path);
+
+ auto gen_relative_header = gen_relative_path / (input_filename + ".h");
+ auto gen_file = gen_path / (input_filename + "_python3.cc");
+
+ std::ofstream out_file;
+ out_file.open(gen_file);
+ if (!out_file.is_open()) {
+ std::cerr << "can't open " << gen_file << std::endl;
+ return false;
+ }
+
+ out_file << "#include <pybind11/pybind11.h>\n";
+ out_file << "#include <pybind11/stl.h>\n";
+ out_file << "\n\n";
+ out_file << "#include " << gen_relative_header << "\n";
+ out_file << "\n\n";
+
+ std::vector<std::string> namespace_list;
+ parse_namespace(root_namespace, gen_relative_path, &namespace_list);
+ generate_namespace_open(namespace_list, out_file);
+ out_file << "\n\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
+ c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
+ const auto* custom_def = dynamic_cast<const CustomFieldDef*>(c.second);
+ custom_def->GenUsing(out_file);
+ }
+ }
+ out_file << "\n\n";
+
+ out_file << "using ::bluetooth::packet::BasePacketBuilder;";
+ out_file << "using ::bluetooth::packet::BitInserter;";
+ out_file << "using ::bluetooth::packet::CustomTypeChecker;";
+ out_file << "using ::bluetooth::packet::Iterator;";
+ out_file << "using ::bluetooth::packet::kLittleEndian;";
+ out_file << "using ::bluetooth::packet::PacketBuilder;";
+ out_file << "using ::bluetooth::packet::BaseStruct;";
+ out_file << "using ::bluetooth::packet::PacketStruct;";
+ out_file << "using ::bluetooth::packet::PacketView;";
+ out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
+ out_file << "\n\n";
+
+ out_file << "namespace py = pybind11;\n\n";
+
+ out_file << "void define_" << input_filename << "_submodule(py::module& parent) {\n\n";
+ out_file << "py::module m = parent.def_submodule(\"" << input_filename << "\", \"A submodule of " << input_filename
+ << "\");\n\n";
+
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
+ EnumGen gen(*enum_def);
+ gen.GenDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ }
+ }
+
+ for (const auto& s : decls.type_defs_queue_) {
+ if (s.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
+ const auto* struct_def = dynamic_cast<const StructDef*>(s.second);
+ struct_def->GenDefinitionPybind11(out_file);
+ out_file << "\n";
+ }
+ }
+
+ for (const auto& packet_def : decls.packet_defs_queue_) {
+ packet_def.second.GenParserDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ }
+
+ for (const auto& p : decls.packet_defs_queue_) {
+ p.second.GenBuilderDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ }
+
+ out_file << "}\n\n";
+
+ generate_namespace_close(namespace_list, out_file);
+
+ out_file.close();
+
+ return true;
+}
+
} // namespace
// TODO(b/141583809): stop leaks
@@ -273,6 +367,10 @@
std::cerr << "Didn't generate cpp headers for " << input_files.front() << std::endl;
return 3;
}
+ if (!generate_pybind11_sources_one_file(declarations, input_files.front(), include_dir, out_dir, root_namespace)) {
+ std::cerr << "Didn't generate pybind11 sources for " << input_files.front() << std::endl;
+ return 4;
+ }
input_files.pop();
}
diff --git a/gd/packet/parser/packet_def.cc b/gd/packet/parser/packet_def.cc
index 1252a1b..2fd4df2 100644
--- a/gd/packet/parser/packet_def.cc
+++ b/gd/packet/parser/packet_def.cc
@@ -84,6 +84,42 @@
s << "};\n";
}
+void PacketDef::GenParserDefinitionPybind11(std::ostream& s) const {
+ s << "py::class_<" << name_ << "View";
+ if (parent_ != nullptr) {
+ s << ", " << parent_->name_ << "View";
+ } else {
+ s << ", PacketView<" << (is_little_endian_ ? "" : "!") << "kLittleEndian>";
+ }
+ s << ">(m, \"" << name_ << "View\")";
+ if (parent_ != nullptr) {
+ s << ".def(py::init([](" << parent_->name_ << "View parent) {";
+ } else {
+ s << ".def(py::init([](PacketView<" << (is_little_endian_ ? "" : "!") << "kLittleEndian> parent) {";
+ }
+ s << "auto view =" << name_ << "View::Create(std::move(parent));";
+ s << "if (!view.IsValid()) { throw std::invalid_argument(\"Bad packet view\"); }";
+ s << "return view; }))";
+
+ s << ".def(py::init(&" << name_ << "View::Create))";
+ std::set<std::string> protected_field_types = {
+ FixedScalarField::kFieldType,
+ FixedEnumField::kFieldType,
+ SizeField::kFieldType,
+ CountField::kFieldType,
+ };
+ const auto& public_fields = fields_.GetFieldsWithoutTypes(protected_field_types);
+ for (const auto& field : public_fields) {
+ auto getter_func_name = field->GetGetterFunctionName();
+ if (getter_func_name.empty()) {
+ continue;
+ }
+ s << ".def(\"" << getter_func_name << "\", &" << name_ << "View::" << getter_func_name << ")";
+ }
+ s << ".def(\"IsValid\", &" << name_ << "View::IsValid)";
+ s << ";\n";
+}
+
void PacketDef::GenParserFieldGetter(std::ostream& s, const PacketField* field) const {
// Start field offset
auto start_field_offset = GetOffsetForField(field->GetName(), false);
@@ -290,6 +326,29 @@
s << "\n";
}
+void PacketDef::GenBuilderDefinitionPybind11(std::ostream& s) const {
+ s << "py::class_<" << name_ << "Builder";
+ if (parent_ != nullptr) {
+ s << ", " << parent_->name_ << "Builder";
+ } else {
+ if (is_little_endian_) {
+ s << ", PacketBuilder<kLittleEndian>";
+ } else {
+ s << ", PacketBuilder<!kLittleEndian>";
+ }
+ }
+ s << ">(m, \"" << name_ << "Builder\")";
+ if (!fields_.HasBody()) {
+ GenBuilderCreatePybind11(s);
+ }
+ s << ".def(\"Serialize\", [](" << name_ << "Builder& builder){";
+ s << "std::vector<uint8_t> bytes;";
+ s << "BitInserter bi(bytes);";
+ s << "builder.Serialize(bi);";
+ s << "return bytes;})";
+ s << ";\n";
+}
+
void PacketDef::GenTestDefine(std::ostream& s) const {
s << "#ifdef PACKET_TESTING\n";
s << "#define DEFINE_AND_INSTANTIATE_" << name_ << "ReflectionTest(...)";
@@ -433,6 +492,81 @@
s << "}\n";
}
+void PacketDef::GenBuilderCreatePybind11(std::ostream& s) const {
+ s << ".def(py::init([](";
+ auto params = GetParamList();
+ std::vector<std::string> constructor_args;
+ std::vector<std::string> keep_alive_args;
+ int i = 1;
+ for (const auto& param : params) {
+ i++;
+ std::stringstream ss;
+ auto param_type = param->GetBuilderParameterType();
+ if (param_type.empty()) {
+ continue;
+ }
+ // Use shared_ptr instead of unique_ptr for the Python interface
+ if (param->BuilderParameterMustBeMoved()) {
+ param_type = util::StringFindAndReplaceAll(param_type, "unique_ptr", "shared_ptr");
+ keep_alive_args.push_back(std::to_string(i));
+ }
+ ss << param_type << " " << param->GetName();
+ constructor_args.push_back(ss.str());
+ }
+ s << util::StringJoin(",", constructor_args) << "){";
+
+ // Deal with move only args
+ for (const auto& param : params) {
+ std::stringstream ss;
+ auto param_type = param->GetBuilderParameterType();
+ if (param_type.empty()) {
+ continue;
+ }
+ if (!param->BuilderParameterMustBeMoved()) {
+ continue;
+ }
+ auto move_only_param_name = param->GetName() + "_move_only";
+ s << param_type << " " << move_only_param_name << ";";
+ if (param->IsContainerField()) {
+ // Assume single layer container
+ s << "for (size_t i = 0; i < " << param->GetName() << ".size(); i++) {";
+ if (param->GetFieldType() == VectorField::kFieldType) {
+ s << move_only_param_name << ".emplace_back(" << param->GetName() << "[i].get());";
+ } else if (param->GetFieldType() == ArrayField::kFieldType) {
+ s << move_only_param_name << "[i].reset(" << param->GetName() << "[i].get());";
+ } else {
+ ERROR() << param << " is not supported by Pybind11";
+ }
+ s << "}";
+ } else {
+ // Release shared_ptr to unique_ptr and leave the Python copy as nullptr and to be garbage collected by Python
+ s << move_only_param_name << ".reset(" << param->GetName() << ".get());";
+ }
+ }
+ s << "return " << name_ << "Builder::Create(";
+ std::vector<std::string> builder_vars;
+ for (const auto& param : params) {
+ std::stringstream ss;
+ auto param_type = param->GetBuilderParameterType();
+ if (param_type.empty()) {
+ continue;
+ }
+ auto param_name = param->GetName();
+ if (param->BuilderParameterMustBeMoved()) {
+ ss << "std::move(" << param_name << "_move_only)";
+ } else {
+ ss << param_name;
+ }
+ builder_vars.push_back(ss.str());
+ }
+ s << util::StringJoin(",", builder_vars) << ");}";
+ if (keep_alive_args.empty()) {
+ s << "))";
+ } else {
+ s << "), py::keep_alive<1," << util::StringJoin(",", keep_alive_args) << ">())";
+ }
+}
+
void PacketDef::GenBuilderParameterChecker(std::ostream& s) const {
FieldList params_to_validate = GetParametersToValidate();
diff --git a/gd/packet/parser/packet_def.h b/gd/packet/parser/packet_def.h
index 1dc2f8a..e8acdc3 100644
--- a/gd/packet/parser/packet_def.h
+++ b/gd/packet/parser/packet_def.h
@@ -33,6 +33,8 @@
void GenParserDefinition(std::ostream& s) const;
+ void GenParserDefinitionPybind11(std::ostream& s) const;
+
void GenParserFieldGetter(std::ostream& s, const PacketField* field) const;
void GenValidator(std::ostream& s) const;
@@ -41,6 +43,8 @@
void GenBuilderDefinition(std::ostream& s) const;
+ void GenBuilderDefinitionPybind11(std::ostream& s) const;
+
void GenTestDefine(std::ostream& s) const;
void GenFuzzTestDefine(std::ostream& s) const;
@@ -49,6 +53,8 @@
void GenBuilderCreate(std::ostream& s) const;
+ void GenBuilderCreatePybind11(std::ostream& s) const;
+
void GenBuilderParameterChecker(std::ostream& s) const;
void GenBuilderConstructor(std::ostream& s) const;
diff --git a/gd/packet/parser/struct_def.cc b/gd/packet/parser/struct_def.cc
index 3691192..bdeb780 100644
--- a/gd/packet/parser/struct_def.cc
+++ b/gd/packet/parser/struct_def.cc
@@ -180,6 +180,24 @@
s << "\n";
}
+void StructDef::GenDefinitionPybind11(std::ostream& s) const {
+ s << "py::class_<" << name_;
+ if (parent_ != nullptr) {
+ s << ", " << parent_->name_;
+ } else {
+ if (is_little_endian_) {
+ s << ", PacketStruct<kLittleEndian>";
+ } else {
+ s << ", PacketStruct<!kLittleEndian>";
+ }
+ }
+ s << ">(m, \"" << name_ << "\")";
+ s << ".def(py::init<>())";
+ s << ".def(\"Serialize\", &" << GetTypeName() << "::Serialize)";
+ s << ".def(\"Parse\", &" << name_ << "::Parse)";
+ s << ";\n";
+}
+
void StructDef::GenConstructor(std::ostream& s) const {
if (parent_ != nullptr) {
s << name_ << "(const " << parent_->name_ << "& parent) : " << parent_->name_ << "(parent) {}";
diff --git a/gd/packet/parser/struct_def.h b/gd/packet/parser/struct_def.h
index c06c472..74c1b04 100644
--- a/gd/packet/parser/struct_def.h
+++ b/gd/packet/parser/struct_def.h
@@ -42,6 +42,8 @@
void GenDefinition(std::ostream& s) const;
+ void GenDefinitionPybind11(std::ostream& s) const;
+
void GenConstructor(std::ostream& s) const;
Size GetStructOffsetForField(std::string field_name) const;
diff --git a/gd/packet/parser/util.h b/gd/packet/parser/util.h
index 982d39a..a8b881d 100644
--- a/gd/packet/parser/util.h
+++ b/gd/packet/parser/util.h
@@ -114,4 +114,24 @@
return std::regex_match(value, enum_regex);
}
+inline std::string StringJoin(const std::string& delimiter, const std::vector<std::string>& vec) {
+ std::stringstream ss;
+ for (size_t i = 0; i < vec.size(); i++) {
+ ss << vec[i];
+ if (i != (vec.size() - 1)) {
+ ss << delimiter;
+ }
+ }
+ return ss.str();
+}
+
+inline std::string StringFindAndReplaceAll(std::string text, const std::string& old, const std::string& replacement) {
+ auto pos = text.find(old);
+ while (pos != std::string::npos) {
+ text.replace(pos, old.size(), replacement);
+ pos = text.find(old, pos + replacement.size());
+ }
+ return text;
+}
+
} // namespace util
diff --git a/gd/packet/python3_module.cc b/gd/packet/python3_module.cc
new file mode 100644
index 0000000..879732b
--- /dev/null
+++ b/gd/packet/python3_module.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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 <cstring>
+#include <memory>
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+#include "packet/base_packet_builder.h"
+#include "packet/bit_inserter.h"
+#include "packet/iterator.h"
+#include "packet/packet_builder.h"
+#include "packet/packet_struct.h"
+#include "packet/packet_view.h"
+#include "packet/parser/checksum_type_checker.h"
+#include "packet/parser/custom_type_checker.h"
+
+namespace py = pybind11;
+
+namespace bluetooth {
+
+namespace hci {
+void define_hci_packets_submodule(py::module&);
+}
+namespace l2cap {
+void define_l2cap_packets_submodule(py::module&);
+}
+namespace security {
+void define_smp_packets_submodule(py::module&);
+}
+
+namespace packet {
+
+using ::bluetooth::packet::BasePacketBuilder;
+using ::bluetooth::packet::BaseStruct;
+using ::bluetooth::packet::BitInserter;
+using ::bluetooth::packet::CustomTypeChecker;
+using ::bluetooth::packet::Iterator;
+using ::bluetooth::packet::kLittleEndian;
+using ::bluetooth::packet::PacketBuilder;
+using ::bluetooth::packet::PacketStruct;
+using ::bluetooth::packet::PacketView;
+using ::bluetooth::packet::parser::ChecksumTypeChecker;
+
+PYBIND11_MODULE(bluetooth_packets_python3, m) {
+ py::class_<BasePacketBuilder>(m, "BasePacketBuilder");
+ py::class_<PacketBuilder<kLittleEndian>, BasePacketBuilder>(m, "PacketBuilderLittleEndian");
+ py::class_<PacketBuilder<!kLittleEndian>, BasePacketBuilder>(m, "PacketBuilderBigEndian");
+ py::class_<BaseStruct>(m, "BaseStruct");
+ py::class_<PacketStruct<kLittleEndian>, BaseStruct>(m, "PacketStructLittleEndian");
+ py::class_<PacketStruct<!kLittleEndian>, BaseStruct>(m, "PacketStructBigEndian");
+ py::class_<Iterator<kLittleEndian>>(m, "IteratorLittleEndian");
+ py::class_<Iterator<!kLittleEndian>>(m, "IteratorBigEndian");
+ py::class_<PacketView<kLittleEndian>>(m, "PacketViewLittleEndian").def(py::init([](std::vector<uint8_t> bytes) {
+ // Make a copy
+ auto bytes_shared = std::make_shared<std::vector<uint8_t>>(bytes);
+ return std::make_unique<PacketView<kLittleEndian>>(bytes_shared);
+ }));
+ py::class_<PacketView<!kLittleEndian>>(m, "PacketViewBigEndian").def(py::init([](std::vector<uint8_t> bytes) {
+ // Make a copy
+ auto bytes_shared = std::make_shared<std::vector<uint8_t>>(bytes);
+ return std::make_unique<PacketView<!kLittleEndian>>(bytes_shared);
+ }));
+
+ bluetooth::hci::define_hci_packets_submodule(m);
+ bluetooth::l2cap::define_l2cap_packets_submodule(m);
+ bluetooth::security::define_smp_packets_submodule(m);
+}
+
+} // namespace packet
+} // namespace bluetooth
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
index 961eae7..b729b38 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
@@ -674,6 +674,7 @@
void DualModeController::HciWriteSecureConnectionHostSupport(
packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
+ properties_.SetExtendedFeatures(properties_.GetExtendedFeatures(1) | 0x8, 1);
SendCommandCompleteSuccess(
bluetooth::hci::OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon.cc b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
index 77491d9..96f6099 100644
--- a/vendor_libs/test_vendor_lib/model/devices/beacon.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
@@ -70,8 +70,7 @@
std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
std::move(ad);
- std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
- for (std::shared_ptr<PhyLayer> phy : le_phys) {
+ for (auto phy : phy_layers_[Phy::Type::LOW_ENERGY]) {
phy->Send(to_send);
}
}
@@ -88,8 +87,7 @@
std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
std::move(scan_response);
- std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
- for (auto phy : le_phys) {
+ for (auto phy : phy_layers_[Phy::Type::LOW_ENERGY]) {
phy->Send(to_send);
}
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
index 0445312..f3fc3e6 100644
--- a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
@@ -43,7 +43,7 @@
properties_.SetPageScanRepetitionMode(0);
properties_.SetClassOfDevice(0x600420);
- properties_.SetSupportedFeatures(0x8779ff9bfe8defff);
+ properties_.SetExtendedFeatures(0x8779ff9bfe8defff, 0);
properties_.SetExtendedInquiryData({
16, // length
9, // Type: Device Name
diff --git a/vendor_libs/test_vendor_lib/model/devices/classic.cc b/vendor_libs/test_vendor_lib/model/devices/classic.cc
index 0838bd5..e8df43a 100644
--- a/vendor_libs/test_vendor_lib/model/devices/classic.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/classic.cc
@@ -32,7 +32,7 @@
'g', 'D', 'e', 'v', 'i', 'c', 'e', '-', 'c', 'l', 'a', 's', 's', 'i', 'c',
'\0'}); // End of data
properties_.SetPageScanRepetitionMode(0);
- properties_.SetSupportedFeatures(0x87593F9bFE8FFEFF);
+ properties_.SetExtendedFeatures(0x87593F9bFE8FFEFF, 0);
page_scan_delay_ms_ = std::chrono::milliseconds(600);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.cc b/vendor_libs/test_vendor_lib/model/devices/device.cc
index 4a03da0..9fdcd5e 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/device.cc
@@ -42,10 +42,10 @@
}
void Device::UnregisterPhyLayer(Phy::Type phy_type, uint32_t factory_id) {
- for (size_t i = 0; i < phy_layers_[phy_type].size(); i++) {
- if (phy_layers_[phy_type][i]->IsFactoryId(factory_id)) {
- phy_layers_[phy_type][i]->Unregister();
- phy_layers_[phy_type].erase(phy_layers_[phy_type].begin() + i);
+ for (const auto phy_layer : phy_layers_[phy_type]) {
+ if (phy_layer->IsFactoryId(factory_id)) {
+ phy_layer->Unregister();
+ phy_layers_[phy_type].remove(phy_layer);
}
}
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.h b/vendor_libs/test_vendor_lib/model/devices/device.h
index 90901df..b985888 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device.h
+++ b/vendor_libs/test_vendor_lib/model/devices/device.h
@@ -18,6 +18,7 @@
#include <chrono>
#include <cstdint>
+#include <list>
#include <map>
#include <string>
#include <vector>
@@ -86,7 +87,7 @@
Phy::Type phy_type);
protected:
- std::map<Phy::Type, std::vector<std::shared_ptr<PhyLayer>>> phy_layers_;
+ std::map<Phy::Type, std::list<std::shared_ptr<PhyLayer>>> phy_layers_;
std::chrono::steady_clock::time_point last_advertisement_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/device_properties.h b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
index d787bb9..b9d03ba 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device_properties.h
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
@@ -49,8 +49,9 @@
return extended_features_[0];
}
- void SetSupportedFeatures(uint64_t features) {
- extended_features_[0] = features;
+ void SetExtendedFeatures(uint64_t features, uint8_t page_number) {
+ ASSERT(page_number < extended_features_.size());
+ extended_features_[page_number] = features;
}
// Specification Version 4.2, Volume 2, Part E, Section 7.4.4
@@ -311,7 +312,7 @@
std::vector<uint8_t> supported_codecs_;
std::vector<uint32_t> vendor_specific_codecs_;
std::vector<uint8_t> supported_commands_;
- std::vector<uint64_t> extended_features_{{0x875b3fd8fe8ffeff, 0x07}};
+ std::vector<uint64_t> extended_features_{{0x875b3fd8fe8ffeff, 0x0f}};
ClassOfDevice class_of_device_{{0, 0, 0}};
std::vector<uint8_t> extended_inquiry_data_;
std::vector<uint8_t> name_;
diff --git a/vendor_libs/test_vendor_lib/model/devices/loopback.cc b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
index dd8d3ed..df0c762 100644
--- a/vendor_libs/test_vendor_lib/model/devices/loopback.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
@@ -80,8 +80,7 @@
std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
std::move(scan_response);
- std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
- for (auto phy : le_phys) {
+ for (auto phy : phy_layers_[Phy::Type::LOW_ENERGY]) {
LOG_INFO("Sending a Scan Response on a Phy");
phy->Send(to_send);
}
diff --git a/vendor_libs/test_vendor_lib/model/devices/sniffer.cc b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
index c4586d1..efdca87 100644
--- a/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
@@ -47,8 +47,10 @@
if (!match_source && !match_dest) {
return;
}
- LOG_INFO("%s %s -> %s (Type %d)", (match_source ? (match_dest ? "<->" : "<--") : "-->"), source.ToString().c_str(),
- dest.ToString().c_str(), static_cast<int>(packet.GetType()));
+ LOG_INFO("%s %s -> %s (Type %s)",
+ (match_source ? (match_dest ? "<->" : "<--") : "-->"),
+ source.ToString().c_str(), dest.ToString().c_str(),
+ model::packets::PacketTypeText(packet.GetType()).c_str());
}
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
index 9f2bc7a..7f0fa33 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
@@ -25,8 +25,12 @@
public:
PhyLayer(Phy::Type phy_type, uint32_t id,
const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive)
- : phy_type_(phy_type), id_(id), transmit_to_device_(device_receive) {}
+ device_receive,
+ uint32_t device_id)
+ : phy_type_(phy_type),
+ id_(id),
+ device_id_(device_id),
+ transmit_to_device_(device_receive) {}
virtual void Send(
const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet) = 0;
@@ -48,11 +52,14 @@
return id_;
}
+ uint32_t GetDeviceId() { return device_id_; }
+
virtual ~PhyLayer() = default;
private:
Phy::Type phy_type_;
uint32_t id_;
+ uint32_t device_id_;
protected:
const std::function<void(model::packets::LinkLayerPacketView)>
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
index e1da9f3..b963ce0 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
@@ -15,6 +15,7 @@
*/
#include "phy_layer_factory.h"
+#include <sstream>
namespace test_vendor_lib {
@@ -31,10 +32,11 @@
std::shared_ptr<PhyLayer> PhyLayerFactory::GetPhyLayer(
const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive) {
- std::shared_ptr<PhyLayer> new_phy =
- std::make_shared<PhyLayerImpl>(phy_type_, next_id_++, device_receive,
- std::shared_ptr<PhyLayerFactory>(this));
+ device_receive,
+ uint32_t device_id) {
+ std::shared_ptr<PhyLayer> new_phy = std::make_shared<PhyLayerImpl>(
+ phy_type_, next_id_++, device_receive, device_id,
+ std::shared_ptr<PhyLayerFactory>(this));
phy_layers_.push_back(new_phy);
return new_phy;
}
@@ -63,16 +65,12 @@
model::packets::LinkLayerPacketView::Create(packet_view);
ASSERT(link_layer_packet_view.IsValid());
- for (const auto phy : phy_layers_) {
- if (id != phy->GetId()) {
- phy->Receive(link_layer_packet_view);
- }
- }
+ Send(link_layer_packet_view, id);
}
void PhyLayerFactory::Send(model::packets::LinkLayerPacketView packet,
uint32_t id) {
- for (const auto phy : phy_layers_) {
+ for (const auto& phy : phy_layers_) {
if (id != phy->GetId()) {
phy->Receive(packet);
}
@@ -80,30 +78,37 @@
}
void PhyLayerFactory::TimerTick() {
- for (auto phy : phy_layers_) {
+ for (auto& phy : phy_layers_) {
phy->TimerTick();
}
}
std::string PhyLayerFactory::ToString() const {
+ std::stringstream factory;
switch (phy_type_) {
case Phy::Type::LOW_ENERGY:
- return "LOW_ENERGY";
+ factory << "LOW_ENERGY: ";
break;
case Phy::Type::BR_EDR:
- return "BR_EDR";
+ factory << "BR_EDR: ";
break;
default:
- return "Unknown";
+ factory << "Unknown: ";
}
+ for (auto& phy : phy_layers_) {
+ factory << phy->GetDeviceId();
+ factory << ",";
+ }
+
+ return factory.str();
}
PhyLayerImpl::PhyLayerImpl(
Phy::Type phy_type, uint32_t id,
const std::function<void(model::packets::LinkLayerPacketView)>&
device_receive,
- const std::shared_ptr<PhyLayerFactory>& factory)
- : PhyLayer(phy_type, id, device_receive), factory_(factory) {}
+ uint32_t device_id, const std::shared_ptr<PhyLayerFactory> factory)
+ : PhyLayer(phy_type, id, device_receive, device_id), factory_(factory) {}
PhyLayerImpl::~PhyLayerImpl() {
Unregister();
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
index 003236a..7d46733 100644
--- a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
@@ -39,7 +39,8 @@
std::shared_ptr<PhyLayer> GetPhyLayer(
const std::function<void(model::packets::LinkLayerPacketView)>&
- device_receive);
+ device_receive,
+ uint32_t device_id);
void UnregisterPhyLayer(uint32_t id);
@@ -65,17 +66,20 @@
PhyLayerImpl(Phy::Type phy_type, uint32_t id,
const std::function<void(model::packets::LinkLayerPacketView)>&
device_receive,
- const std::shared_ptr<PhyLayerFactory>& factory);
+ uint32_t device_id,
+ const std::shared_ptr<PhyLayerFactory> factory);
virtual ~PhyLayerImpl() override;
virtual void Send(
const std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet)
override;
- virtual void Send(model::packets::LinkLayerPacketView packet) override;
- virtual void Receive(model::packets::LinkLayerPacketView packet) override;
- virtual void Unregister() override;
- virtual bool IsFactoryId(uint32_t factory_id) override;
- virtual void TimerTick() override;
+ void Send(model::packets::LinkLayerPacketView packet) override;
+ void Receive(model::packets::LinkLayerPacketView packet) override;
+ void Unregister() override;
+ bool IsFactoryId(uint32_t factory_id) override;
+ void TimerTick() override;
+
+ uint32_t device_id_;
private:
std::shared_ptr<PhyLayerFactory> factory_;
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_model.cc b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
index 2a7e5a5..688b7dc 100644
--- a/vendor_libs/test_vendor_lib/model/setup/test_model.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
@@ -134,7 +134,8 @@
dev->RegisterPhyLayer(phy->second->GetPhyLayer(
[dev](model::packets::LinkLayerPacketView packet) {
dev->IncomingPacket(packet);
- }));
+ },
+ device->first));
}
void TestModel::DelDeviceFromPhy(size_t dev_index, size_t phy_index) {