Merge "Rootcanal: Get a MAC from a property"
diff --git a/gd/Android.bp b/gd/Android.bp
index 19eaec3..46108c6 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -363,7 +363,7 @@
tools: [
"bluetooth_packetgen",
],
- cmd: "$(location bluetooth_packetgen) --include=system/bt/gd --out=$(genDir) $(in)",
+ cmd: "$(location bluetooth_packetgen) --include=system/bt/gd --out=$(genDir) --num_shards=5 $(in)",
srcs: [
"hci/hci_packets.pdl",
"l2cap/l2cap_packets.pdl",
@@ -371,8 +371,23 @@
],
out: [
"hci/hci_packets_python3.cc",
+ "hci/hci_packets_python3_shard_0.cc",
+ "hci/hci_packets_python3_shard_1.cc",
+ "hci/hci_packets_python3_shard_2.cc",
+ "hci/hci_packets_python3_shard_3.cc",
+ "hci/hci_packets_python3_shard_4.cc",
"l2cap/l2cap_packets_python3.cc",
+ "l2cap/l2cap_packets_python3_shard_0.cc",
+ "l2cap/l2cap_packets_python3_shard_1.cc",
+ "l2cap/l2cap_packets_python3_shard_2.cc",
+ "l2cap/l2cap_packets_python3_shard_3.cc",
+ "l2cap/l2cap_packets_python3_shard_4.cc",
"security/smp_packets_python3.cc",
+ "security/smp_packets_python3_shard_0.cc",
+ "security/smp_packets_python3_shard_1.cc",
+ "security/smp_packets_python3_shard_2.cc",
+ "security/smp_packets_python3_shard_3.cc",
+ "security/smp_packets_python3_shard_4.cc",
],
}
@@ -590,7 +605,11 @@
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",
+ // Commenting out the Linux suffix so that cpython-38-x86_64-linux-gnu
+ // Python 3.8 can also import the untagged .so library per PEP 3149
+ // Keep this change until Android py3-cmd can run ACTS, gRPC and can
+ // Export Python native symbols such as PyType_Type
+ // suffix: ".cpython-38android-x86_64-linux-gnu",
},
windows: {
enabled: false,
diff --git a/gd/cert/bluetooth_packets_python3_setup.py b/gd/cert/bluetooth_packets_python3_setup.py
new file mode 100644
index 0000000..bce14f0
--- /dev/null
+++ b/gd/cert/bluetooth_packets_python3_setup.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+
+# Usage:
+# 1. Run envsetup and lunch first in an Android checkout
+# 2. Make target bluetooth_packets_python3 that will generate C++ sources for the
+# Extension
+# 3. Build only:
+# python3 bluetooth_packets_python3_setup.py build_ext
+# Then Find the .so file in build/lib.linux-x86_64-3.X
+# 4. Install:
+# python3 bluetooth_packets_python3_setup.py install --user
+
+
+import os
+import glob
+from setuptools import setup, Extension
+
+ANDROID_BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+PYBIND11_INCLUDE_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "external/python/pybind11/include")
+GD_DIR = os.path.join(ANDROID_BUILD_TOP, "system/bt/gd")
+BT_PACKETS_GEN_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "out/soong/.intermediates/system/bt/gd/BluetoothGeneratedPackets_h/gen")
+BT_PACKETS_PY3_GEN_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "out/soong/.intermediates/system/bt/gd/BluetoothGeneratedPackets_python3_cc/gen")
+
+BT_PACKETS_BASE_SRCS = [
+ os.path.join(GD_DIR, "l2cap/fcs.cc"),
+ os.path.join(GD_DIR, "packet/bit_inserter.cc"),
+ os.path.join(GD_DIR, "packet/byte_inserter.cc"),
+ os.path.join(GD_DIR, "packet/byte_observer.cc"),
+ os.path.join(GD_DIR, "packet/iterator.cc"),
+ os.path.join(GD_DIR, "packet/fragmenting_inserter.cc"),
+ os.path.join(GD_DIR, "packet/packet_view.cc"),
+ os.path.join(GD_DIR, "packet/raw_builder.cc"),
+ os.path.join(GD_DIR, "packet/view.cc"),
+]
+
+BT_PACKETS_PY3_SRCs = \
+ [os.path.join(GD_DIR, "packet/python3_module.cc")] \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "hci", "*.cc")) \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "l2cap", "*.cc")) \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "security", "*.cc"))
+
+bluetooth_packets_python3_module = Extension('bluetooth_packets_python3',
+ sources=BT_PACKETS_BASE_SRCS + BT_PACKETS_PY3_SRCs,
+ include_dirs=[GD_DIR,
+ BT_PACKETS_GEN_DIR,
+ BT_PACKETS_PY3_GEN_DIR,
+ PYBIND11_INCLUDE_DIR],
+ extra_compile_args=['-std=c++17']
+ )
+
+setup(name='bluetooth_packets_python3',
+ version='1.0',
+ author="Android Open Source Project",
+ description="""Bluetooth Packet Library""",
+ ext_modules=[bluetooth_packets_python3_module],
+ py_modules=["bluetooth_packets_python3"],
+ )
diff --git a/gd/cert/run_cert.sh b/gd/cert/run_cert.sh
index 81fe91e..a85b994 100755
--- a/gd/cert/run_cert.sh
+++ b/gd/cert/run_cert.sh
@@ -1,3 +1,5 @@
#! /bin/bash
-act.py -c $ANDROID_BUILD_TOP/system/bt/gd/cert/host_only_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
+# For bluetooth_packets_python3
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 `which act.py` -c $ANDROID_BUILD_TOP/system/bt/gd/cert/host_only_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
diff --git a/gd/cert/run_device_cert.sh b/gd/cert/run_device_cert.sh
index 44e5a89..7566f65 100755
--- a/gd/cert/run_device_cert.sh
+++ b/gd/cert/run_device_cert.sh
@@ -1,3 +1,5 @@
#! /bin/bash
-act.py -c $ANDROID_BUILD_TOP/system/bt/gd/cert/android_devices_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
+# For bluetooth_packets_python3
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 `which act.py` -c $ANDROID_BUILD_TOP/system/bt/gd/cert/android_devices_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
diff --git a/gd/cert/set_up_acts.sh b/gd/cert/set_up_acts.sh
index c8fa38b..ad4e775 100755
--- a/gd/cert/set_up_acts.sh
+++ b/gd/cert/set_up_acts.sh
@@ -46,9 +46,15 @@
popd
}
-function SetupPython3 {
- echo "Setting up python3"
- sudo apt-get install python3-dev
+function SetupPython38 {
+ echo "Setting up python3.8"
+ sudo apt-get install python3.8-dev
+}
+
+function CompileBluetoothPacketsPython3 {
+ echo "bluetooth_packets_python3 is not found, compiling"
+ croot
+ make -j bluetooth_packets_python3
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]] ; then
@@ -60,16 +66,41 @@
SetUpAndroidBuild
fi
-## Check python3 is installed properly
-dpkg -l python3-dev > /dev/null 2>&1
+## Check python3.8 is installed properly
+## Need Python 3.8 because bluetooth_packets_python3 is compiled against
+## Python 3.8 headers
+dpkg -l python3.8-dev > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
- SetupPython3
+ SetupPython38
+fi
+
+## Check bluetooth_packets_python3 is compiled succssfully
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 -c "
+import bluetooth_packets_python3 as bp3
+bp3.BaseStruct
+"
+if [[ $? -ne 0 ]] ; then
+ pushd .
+ CompileBluetoothPacketsPython3
+ popd
+ python3.8 -c "
+import bluetooth_packets_python3 as bp3
+bp3.BaseStruct
+"
+ if [[ $? -ne 0 ]] ; then
+ echo "Setup failed as bluetooth_packets_python3 cannot be found"
+ else
+ echo "Found bluetooth_packets_python3 after compilation"
+ fi
+else
+ echo "Found bluetooth_packets_python3"
fi
## All is good now so go ahead with the acts setup
pushd .
cd $ANDROID_BUILD_TOP/tools/test/connectivity/acts/framework/
-sudo python3 setup.py develop
+sudo python3.8 setup.py develop
if [[ $? -eq 0 ]] ; then
echo "cert setup complete"
else
diff --git a/gd/hci/acl_fragmenter.cc b/gd/hci/acl_fragmenter.cc
index 189e52d..fa3b31d 100644
--- a/gd/hci/acl_fragmenter.cc
+++ b/gd/hci/acl_fragmenter.cc
@@ -29,6 +29,7 @@
std::vector<std::unique_ptr<packet::RawBuilder>> to_return;
packet::FragmentingInserter fragmenting_inserter(mtu_, std::back_insert_iterator(to_return));
packet_->Serialize(fragmenting_inserter);
+ fragmenting_inserter.finalize();
return to_return;
}
diff --git a/gd/hci/address.h b/gd/hci/address.h
index a8f515c..3bc507f 100644
--- a/gd/hci/address.h
+++ b/gd/hci/address.h
@@ -18,6 +18,7 @@
#pragma once
+#include <cstring>
#include <string>
namespace bluetooth {
diff --git a/gd/hci/hci_packets.pdl b/gd/hci/hci_packets.pdl
index b591ec9..4fac6c6 100644
--- a/gd/hci/hci_packets.pdl
+++ b/gd/hci/hci_packets.pdl
@@ -1530,7 +1530,7 @@
authentication_enable : AuthenticationEnable,
}
-packet WriteAuthenticationEnable : CommandPacket (op_code = WRITE_AUTHENTICATION_ENABLE) {
+packet WriteAuthenticationEnable : SecurityCommand (op_code = WRITE_AUTHENTICATION_ENABLE) {
authentication_enable : AuthenticationEnable,
}
@@ -1911,7 +1911,7 @@
secure_connections_host_support : Enable,
}
-packet WriteSecureConnectionsHostSupport : CommandPacket (op_code = WRITE_SECURE_CONNECTIONS_HOST_SUPPORT) {
+packet WriteSecureConnectionsHostSupport : SecurityCommand (op_code = WRITE_SECURE_CONNECTIONS_HOST_SUPPORT) {
secure_connections_host_support : Enable,
}
diff --git a/gd/hci/security_interface.h b/gd/hci/security_interface.h
index efb20d0..ea15aa0 100644
--- a/gd/hci/security_interface.h
+++ b/gd/hci/security_interface.h
@@ -43,6 +43,7 @@
hci::EventCode::IO_CAPABILITY_REQUEST, hci::EventCode::IO_CAPABILITY_RESPONSE,
hci::EventCode::REMOTE_OOB_DATA_REQUEST, hci::EventCode::SIMPLE_PAIRING_COMPLETE,
hci::EventCode::USER_PASSKEY_NOTIFICATION, hci::EventCode::KEYPRESS_NOTIFICATION,
+ hci::EventCode::USER_CONFIRMATION_REQUEST, hci::EventCode::USER_PASSKEY_REQUEST,
};
};
} // namespace hci
diff --git a/gd/l2cap/Android.bp b/gd/l2cap/Android.bp
index 649f618..3d65446 100644
--- a/gd/l2cap/Android.bp
+++ b/gd/l2cap/Android.bp
@@ -42,6 +42,8 @@
"classic/internal/fixed_channel_service_manager_test.cc",
"classic/internal/link_manager_test.cc",
"classic/internal/signalling_manager_test.cc",
+ "internal/basic_mode_channel_data_controller_test.cc",
+ "internal/enhanced_retransmission_mode_channel_data_controller_test.cc",
"internal/fixed_channel_allocator_test.cc",
"internal/receiver_test.cc",
"internal/scheduler_fifo_test.cc",
diff --git a/gd/l2cap/cid.h b/gd/l2cap/cid.h
index 9a21abb..729272c 100644
--- a/gd/l2cap/cid.h
+++ b/gd/l2cap/cid.h
@@ -36,5 +36,7 @@
constexpr Cid kSmpCid = 6;
constexpr Cid kSmpBrCid = 7;
+constexpr Cid kClassicPairingTriggerCid = kLastFixedChannel - 1;
+
} // namespace l2cap
} // namespace bluetooth
diff --git a/gd/l2cap/classic/cert/api.proto b/gd/l2cap/classic/cert/api.proto
index 8492323..c7e68d5 100644
--- a/gd/l2cap/classic/cert/api.proto
+++ b/gd/l2cap/classic/cert/api.proto
@@ -24,6 +24,7 @@
rpc SendInformationResponse(InformationResponse) returns (SendInformationResponseResult) {}
rpc FetchL2capLog(FetchL2capLogRequest) returns (stream FetchL2capLogResponse) {}
+ rpc StopFetchingL2capLog(StopFetchingL2capLogRequest) returns (StopFetchingL2capLogResponse) {}
}
message L2capPacket {
@@ -58,10 +59,27 @@
message SendConnectionResponseResult {}
+enum ChannelRetransmissionFlowControlMode {
+ BASIC = 0;
+ ERTM = 3;
+ STREAM = 4;
+}
+
+message ChannelRetransmissionFlowControlConfig {
+ ChannelRetransmissionFlowControlMode mode = 1;
+ uint32 tx_window = 2;
+ uint32 max_transmit = 3;
+ uint32 retransmit_timeout = 4;
+ uint32 monitor_timeout = 5;
+ uint32 mps = 6;
+}
+
message ConfigurationRequest {
uint32 dcid = 1;
uint32 signal_id = 2;
- repeated string configuration = 3;
+ uint32 mtu = 3;
+ ChannelRetransmissionFlowControlConfig retransmission_config = 4;
+ bool fcs = 5;
}
message SendConfigurationRequestResult {}
@@ -69,7 +87,9 @@
message ConfigurationResponse {
uint32 scid = 1;
uint32 signal_id = 2;
- repeated string configuration = 3;
+ uint32 mtu = 3;
+ ChannelRetransmissionFlowControlConfig retransmission_config = 4;
+ bool fcs = 5;
}
message SendConfigurationResponseResult {}
@@ -107,6 +127,7 @@
InformationRequestType type = 1;
uint32 data = 2;
uint32 signal_id = 3;
+ uint32 information_value = 4;
}
message SendInformationResponseResult {}
@@ -153,3 +174,7 @@
LinkDown link_down = 21;
}
}
+
+message StopFetchingL2capLogRequest {}
+
+message StopFetchingL2capLogResponse {}
diff --git a/gd/l2cap/classic/cert/cert.cc b/gd/l2cap/classic/cert/cert.cc
index 2e2ac59..63c8593 100644
--- a/gd/l2cap/classic/cert/cert.cc
+++ b/gd/l2cap/classic/cert/cert.cc
@@ -105,7 +105,22 @@
::grpc::Status SendConfigurationRequest(
::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request,
::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override {
- auto builder = ConfigurationRequestBuilder::Create(request->signal_id(), request->dcid(), Continuation::END, {});
+ std::vector<std::unique_ptr<ConfigurationOption>> config;
+ if (request->retransmission_config().mode() == ChannelRetransmissionFlowControlMode::ERTM) {
+ auto option = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
+ option->mode_ = RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
+ option->tx_window_size_ = 10;
+ option->max_transmit_ = 20;
+ option->retransmission_time_out_ = 2000;
+ option->monitor_time_out_ = 12000;
+ option->maximum_pdu_size_ = 1010;
+ config.push_back(std::move(option));
+ auto no_fcs = std::make_unique<FrameCheckSequenceOption>();
+ no_fcs->fcs_type_ = FcsType::NO_FCS;
+ config.push_back(std::move(no_fcs));
+ }
+ auto builder = ConfigurationRequestBuilder::Create(request->signal_id(), request->dcid(), Continuation::END,
+ std::move(config));
auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
outgoing_packet_queue_.push(std::move(l2cap_builder));
send_packet_from_queue();
@@ -115,8 +130,19 @@
::grpc::Status SendConfigurationResponse(
::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationResponse* request,
::bluetooth::l2cap::classic::cert::SendConfigurationResponseResult* response) override {
+ std::vector<std::unique_ptr<ConfigurationOption>> config;
+ if (request->retransmission_config().mode() == ChannelRetransmissionFlowControlMode::ERTM) {
+ auto option = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
+ option->mode_ = RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
+ option->tx_window_size_ = 10;
+ option->max_transmit_ = 20;
+ option->retransmission_time_out_ = 2000;
+ option->monitor_time_out_ = 12000;
+ option->maximum_pdu_size_ = 1010;
+ config.push_back(std::move(option));
+ }
auto builder = ConfigurationResponseBuilder::Create(request->signal_id(), request->scid(), Continuation::END,
- ConfigurationResponseResult::SUCCESS, {});
+ ConfigurationResponseResult::SUCCESS, std::move(config));
auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
outgoing_packet_queue_.push(std::move(l2cap_builder));
send_packet_from_queue();
@@ -183,7 +209,7 @@
switch (request->type()) {
case InformationRequestType::CONNECTIONLESS_MTU: {
auto builder = InformationResponseConnectionlessMtuBuilder::Create(request->signal_id(),
- InformationRequestResult::NOT_SUPPORTED, 0);
+ InformationRequestResult::SUCCESS, 100);
auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
outgoing_packet_queue_.push(std::move(l2cap_builder));
send_packet_from_queue();
@@ -191,7 +217,7 @@
}
case InformationRequestType::EXTENDED_FEATURES: {
auto builder = InformationResponseExtendedFeaturesBuilder::Create(
- request->signal_id(), InformationRequestResult::NOT_SUPPORTED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ request->signal_id(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0);
auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
outgoing_packet_queue_.push(std::move(l2cap_builder));
send_packet_from_queue();
@@ -224,7 +250,8 @@
::grpc::Status FetchL2capLog(::grpc::ServerContext* context, const FetchL2capLogRequest* request,
::grpc::ServerWriter<FetchL2capLogResponse>* writer) override {
- while (!context->IsCancelled()) {
+ fetching_l2cap_log_ = true;
+ while (!context->IsCancelled() && fetching_l2cap_log_) {
if (!l2cap_log_.empty()) {
auto& response = l2cap_log_.front();
writer->Write(response);
@@ -241,6 +268,16 @@
}
return ::grpc::Status::OK;
}
+
+ ::grpc::Status StopFetchingL2capLog(
+ ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::StopFetchingL2capLogRequest* request,
+ ::bluetooth::l2cap::classic::cert::StopFetchingL2capLogResponse* response) override {
+ fetching_l2cap_log_ = false;
+ l2cap_log_cv_.notify_one();
+ return ::grpc::Status::OK;
+ }
+
+ bool fetching_l2cap_log_ = false;
std::mutex l2cap_log_mutex_;
std::queue<FetchL2capLogResponse> l2cap_log_;
std::condition_variable l2cap_log_cv_;
@@ -393,15 +430,31 @@
auto type = information_response_view.GetInfoType();
switch (type) {
case InformationRequestInfoType::CONNECTIONLESS_MTU: {
+ auto view = InformationResponseConnectionlessMtuView::Create(information_response_view);
+ if (!view.IsValid()) {
+ return;
+ }
log_response.mutable_information_response()->set_type(InformationRequestType::CONNECTIONLESS_MTU);
+ log_response.mutable_information_response()->set_information_value(view.GetConnectionlessMtu());
break;
}
case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
+ auto view = InformationResponseExtendedFeaturesView::Create(information_response_view);
+ if (!view.IsValid()) {
+ return;
+ }
log_response.mutable_information_response()->set_type(InformationRequestType::EXTENDED_FEATURES);
+ int mask = view.GetEnhancedRetransmissionMode() << 3 | view.GetFcsOption() << 5;
+ log_response.mutable_information_response()->set_information_value(mask);
break;
}
case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
+ auto view = InformationResponseFixedChannelsView::Create(information_response_view);
+ if (!view.IsValid()) {
+ return;
+ }
log_response.mutable_information_response()->set_type(InformationRequestType::FIXED_CHANNELS);
+ log_response.mutable_information_response()->set_information_value(view.GetFixedChannels());
break;
}
}
diff --git a/gd/l2cap/classic/cert/simple_l2cap_test.py b/gd/l2cap/classic/cert/simple_l2cap_test.py
index d0fafb3..38d39b6 100644
--- a/gd/l2cap/classic/cert/simple_l2cap_test.py
+++ b/gd/l2cap/classic/cert/simple_l2cap_test.py
@@ -74,6 +74,9 @@
def is_command_reject(log):
return log.HasField("command_reject")
+def basic_frame_to_enhanced_information_frame(information_payload):
+ return information_payload[2:]
+
class SimpleL2capTest(GdBaseTestClass):
def setup_test(self):
self.device_under_test = self.gd_devices[0]
@@ -105,21 +108,30 @@
log_event_handler = EventHandler()
self.next_scid = 0x40
self.scid_dcid_map = {}
+ self.retransmission_mode = l2cap_cert_pb2.ChannelRetransmissionFlowControlMode.BASIC
def handle_connection_request(log):
log = log.connection_request
self.cert_device.l2cap.SendConnectionResponse(l2cap_cert_pb2.ConnectionResponse(dcid=self.next_scid,scid=log.scid,
signal_id=log.signal_id))
self.scid_dcid_map[self.next_scid] = log.scid
self.next_scid += 1
- self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(dcid=log.scid,
- signal_id=log.signal_id+1))
+ self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(
+ dcid=log.scid,
+ signal_id=log.signal_id+1,
+ retransmission_config=l2cap_cert_pb2.ChannelRetransmissionFlowControlConfig(
+ mode=self.retransmission_mode
+ )))
log_event_handler.on(is_connection_request, handle_connection_request)
def handle_connection_response(log):
log = log.connection_response
self.scid_dcid_map[log.scid] = log.dcid
- self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(dcid=log.dcid,
- signal_id=log.signal_id+1))
+ self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest(
+ dcid=log.dcid,
+ signal_id=log.signal_id+1,
+ retransmission_config=l2cap_cert_pb2.ChannelRetransmissionFlowControlConfig(
+ mode=self.retransmission_mode
+ )))
log_event_handler.on(is_connection_response, handle_connection_response)
def handle_configuration_request(log):
@@ -127,8 +139,10 @@
if log.dcid not in self.scid_dcid_map:
return
dcid = self.scid_dcid_map[log.dcid]
- self.cert_device.l2cap.SendConfigurationResponse(l2cap_cert_pb2.ConfigurationResponse(scid=dcid,
- signal_id=log.signal_id))
+ self.cert_device.l2cap.SendConfigurationResponse(l2cap_cert_pb2.ConfigurationResponse(
+ scid=dcid,
+ signal_id=log.signal_id,
+ ))
log_event_handler.on(is_configuration_request, handle_configuration_request)
def handle_disconnection_request(log):
@@ -168,7 +182,7 @@
self.event_handler.execute(logs)
assert self.dut_address in link_up_handled
- def _open_channel(self, scid=0x0101, psm=0x01):
+ def _open_channel(self, scid=0x0101, psm=0x33):
self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=psm))
configuration_response_handled = []
@@ -184,10 +198,38 @@
def test_connect(self):
self._setup_link()
self._open_channel(scid=0x0101)
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
+
+ def test_connect_and_send_data_ertm_no_segmentation(self):
+ self.retransmission_mode = l2cap_cert_pb2.ChannelRetransmissionFlowControlMode.ERTM
+ self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
+ self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x33, retransmission_mode=l2cap_facade_pb2.RetransmissionFlowControlMode.ERTM))
+ self._setup_link()
+ scid = 0x0101
+ self._open_channel(scid=scid)
+ self.device_under_test.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=2, payload=b"123"))
+
+ data_received = []
+ event_handler = EventHandler()
+ def on_data_received(log):
+ log = log.data_packet
+ if (log.channel == scid):
+ log.payload = basic_frame_to_enhanced_information_frame(log.payload)
+ data_received.append((log.channel, log.payload))
+ event_handler.on(lambda log : log.HasField("data_packet"), on_data_received)
+ logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+ event_handler.execute(logs)
+ assert (2, b"123") in data_received
+
+ self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'*34))
+ logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+ event_handler.execute(logs)
+ assert (scid, b"abc"*34) in data_received
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
def test_connect_and_send_data(self):
self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
- self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x01))
+ self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x33))
self._setup_link()
scid = 0x0101
self._open_channel(scid=scid)
@@ -203,15 +245,17 @@
event_handler.execute(logs)
assert (2, b"123") in data_received
- self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=1, payload=b'abc'))
+ self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
event_handler.execute(logs)
assert (scid, b"abc") in data_received
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
def test_open_two_channels(self):
self._setup_link()
self._open_channel(scid=0x0101, psm=0x1)
self._open_channel(scid=0x0102, psm=0x3)
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
def test_accept_disconnect(self):
"""
@@ -225,6 +269,7 @@
def handle_disconnection_response(log):
log = log.disconnection_response
disconnection_response_handled.append((log.scid, log.dcid))
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
self.event_handler.on(is_disconnection_response, handle_disconnection_response)
self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest(scid=scid, dcid=dcid, signal_id=2))
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
@@ -262,11 +307,13 @@
initiate the configuration procedure.
"""
psm = 1
+ # TODO: Use another test case
self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=psm))
connection_request = []
def handle_connection_request(log):
log = log.connection_request
connection_request.append(log.psm)
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
self.event_handler.on(is_connection_request, handle_connection_request)
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
self.event_handler.execute(logs)
@@ -285,6 +332,7 @@
def handle_echo_response(log):
log = log.echo_response
echo_response.append(log.signal_id)
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
self.event_handler.on(is_echo_response, handle_echo_response)
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
self.event_handler.execute(logs)
@@ -303,6 +351,7 @@
def handle_command_reject(log):
log = log.command_reject
command_reject.append(log.signal_id)
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
self.event_handler.on(is_command_reject, handle_command_reject)
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
self.event_handler.execute(logs)
@@ -321,7 +370,34 @@
def handle_info_response(log):
log = log.information_response
info_response.append((log.signal_id, log.type))
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
self.event_handler.on(is_information_response, handle_info_response)
logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
self.event_handler.execute(logs)
assert (signal_id, l2cap_cert_pb2.InformationRequestType.FIXED_CHANNELS) in info_response
+
+
+ def test_extended_feature_info_response_ertm(self):
+ """
+ L2CAP/EXF/BV-01-C [Extended Features Information Response for Enhanced
+ Retransmission Mode]
+ """
+ self._setup_link()
+ signal_id = 3
+ self.cert_device.l2cap.SendInformationRequest(
+ l2cap_cert_pb2.InformationRequest(
+ type=l2cap_cert_pb2.InformationRequestType.EXTENDED_FEATURES, signal_id=signal_id))
+ info_response = []
+ def handle_info_response(log):
+ log = log.information_response
+ info_response.append((log.signal_id, log.type, log.information_value))
+ self.cert_device.l2cap.StopFetchingL2capLog(l2cap_cert_pb2.StopFetchingL2capLogRequest())
+ self.event_handler.on(is_information_response, handle_info_response)
+ logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+ self.event_handler.execute(logs)
+ expected_log_type = l2cap_cert_pb2.InformationRequestType.EXTENDED_FEATURES
+ expected_mask = 1 << 3
+ assert len(info_response) == 1
+ assert info_response[0][0] == signal_id
+ assert info_response[0][1] == expected_log_type
+ assert info_response[0][2] | expected_mask == expected_mask
diff --git a/gd/l2cap/classic/dynamic_channel_configuration_option.h b/gd/l2cap/classic/dynamic_channel_configuration_option.h
new file mode 100644
index 0000000..3f3cc02
--- /dev/null
+++ b/gd/l2cap/classic/dynamic_channel_configuration_option.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "l2cap/mtu.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace classic {
+
+/**
+ * Configuration Option specified by L2CAP Channel user on a dynamic channel. L2CAP module will configure the channel
+ * based on user provided option.
+ */
+struct DynamicChannelConfigurationOption {
+ enum class RetransmissionAndFlowControlMode {
+ L2CAP_BASIC,
+ ENHANCED_RETRANSMISSION,
+ };
+ /**
+ * Retransmission and flow control mode. Currently L2CAP_BASIC and ENHANCED_RETRANSMISSION.
+ * If the remote doesn't support a mode, it might fall back to basic, as this is a negotiable option.
+ */
+ RetransmissionAndFlowControlMode channel_mode = RetransmissionAndFlowControlMode::L2CAP_BASIC;
+
+ /**
+ * Maximum SDU size that the L2CAP Channel user is able to process.
+ */
+ Mtu incoming_mtu = kDefaultClassicMtu;
+};
+
+} // namespace classic
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/dynamic_channel_manager.cc b/gd/l2cap/classic/dynamic_channel_manager.cc
index 915b8fd..123fdd4 100644
--- a/gd/l2cap/classic/dynamic_channel_manager.cc
+++ b/gd/l2cap/classic/dynamic_channel_manager.cc
@@ -24,12 +24,14 @@
namespace l2cap {
namespace classic {
-bool DynamicChannelManager::ConnectChannel(hci::Address device, Psm psm, OnConnectionOpenCallback on_connection_open,
+bool DynamicChannelManager::ConnectChannel(hci::Address device, DynamicChannelConfigurationOption configuration_option,
+ Psm psm, OnConnectionOpenCallback on_connection_open,
OnConnectionFailureCallback on_fail_callback, os::Handler* handler) {
internal::Link::PendingDynamicChannelConnection pending_dynamic_channel_connection{
.handler_ = handler,
.on_open_callback_ = std::move(on_connection_open),
.on_fail_callback_ = std::move(on_fail_callback),
+ .configuration_ = configuration_option,
};
l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectDynamicChannelServices,
common::Unretained(link_manager_), device,
@@ -38,13 +40,16 @@
return true;
}
-bool DynamicChannelManager::RegisterService(Psm psm, const SecurityPolicy& security_policy,
+bool DynamicChannelManager::RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
+ const SecurityPolicy& security_policy,
OnRegistrationCompleteCallback on_registration_complete,
OnConnectionOpenCallback on_connection_open, os::Handler* handler) {
internal::DynamicChannelServiceImpl::PendingRegistration pending_registration{
.user_handler_ = handler,
.on_registration_complete_callback_ = std::move(on_registration_complete),
- .on_connection_open_callback_ = std::move(on_connection_open)};
+ .on_connection_open_callback_ = std::move(on_connection_open),
+ .configuration_ = configuration_option,
+ };
l2cap_layer_handler_->Post(common::BindOnce(&internal::DynamicChannelServiceManagerImpl::Register,
common::Unretained(service_manager_), psm,
std::move(pending_registration)));
diff --git a/gd/l2cap/classic/dynamic_channel_manager.h b/gd/l2cap/classic/dynamic_channel_manager.h
index b6c0518..340d68d 100644
--- a/gd/l2cap/classic/dynamic_channel_manager.h
+++ b/gd/l2cap/classic/dynamic_channel_manager.h
@@ -20,6 +20,7 @@
#include "hci/acl_manager.h"
#include "hci/address.h"
#include "l2cap/classic/dynamic_channel.h"
+#include "l2cap/classic/dynamic_channel_configuration_option.h"
#include "l2cap/classic/dynamic_channel_service.h"
#include "l2cap/l2cap_packets.h"
#include "l2cap/psm.h"
@@ -89,11 +90,13 @@
* @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
* @param on_fail_callback: A callback to indicate connection failure along with a status code.
* @param handler: The handler context in which to execute the @callback parameters.
+ * @param configuration_option: The configuration options for this channel
*
* Returns: true if connection was able to be initiated, false otherwise.
*/
- bool ConnectChannel(hci::Address device, Psm psm, OnConnectionOpenCallback on_connection_open,
- OnConnectionFailureCallback on_fail_callback, os::Handler* handler);
+ bool ConnectChannel(hci::Address device, DynamicChannelConfigurationOption configuration_option, Psm psm,
+ OnConnectionOpenCallback on_connection_open, OnConnectionFailureCallback on_fail_callback,
+ os::Handler* handler);
/**
* Register a service to receive incoming connections bound to a specific channel.
@@ -114,9 +117,10 @@
* not SUCCESS, it means service is not registered due to reasons like PSM already take
* @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
* @param handler: The handler context in which to execute the @callback parameter.
+ * @param configuration_option: The configuration options for this channel
*/
- bool RegisterService(Psm psm, const SecurityPolicy& security_policy,
- OnRegistrationCompleteCallback on_registration_complete,
+ bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
+ const SecurityPolicy& security_policy, OnRegistrationCompleteCallback on_registration_complete,
OnConnectionOpenCallback on_connection_open, os::Handler* handler);
friend class L2capClassicModule;
diff --git a/gd/l2cap/classic/facade.cc b/gd/l2cap/classic/facade.cc
index f2b2df3..9613c75 100644
--- a/gd/l2cap/classic/facade.cc
+++ b/gd/l2cap/classic/facade.cc
@@ -99,8 +99,9 @@
const ::bluetooth::l2cap::classic::OpenChannelRequest* request,
::google::protobuf::Empty* response) override {
auto psm = request->psm();
+ auto mode = request->mode();
dynamic_channel_helper_map_.emplace(
- psm, std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, psm));
+ psm, std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, psm, mode));
hci::Address peer;
ASSERT(hci::Address::FromString(request->remote().address(), peer));
dynamic_channel_helper_map_[psm]->Connect(peer);
@@ -183,27 +184,37 @@
::grpc::Status SetDynamicChannel(::grpc::ServerContext* context, const SetEnableDynamicChannelRequest* request,
google::protobuf::Empty* response) override {
- dynamic_channel_helper_map_.emplace(request->psm(), std::make_unique<L2capDynamicChannelHelper>(
- this, l2cap_layer_, facade_handler_, request->psm()));
+ dynamic_channel_helper_map_.emplace(
+ request->psm(), std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, request->psm(),
+ request->retransmission_mode()));
return ::grpc::Status::OK;
}
class L2capDynamicChannelHelper {
public:
L2capDynamicChannelHelper(L2capModuleFacadeService* service, L2capClassicModule* l2cap_layer, os::Handler* handler,
- Psm psm)
+ Psm psm, RetransmissionFlowControlMode mode)
: facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm) {
dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager();
+ DynamicChannelConfigurationOption configuration_option;
+ if (mode == RetransmissionFlowControlMode::BASIC) {
+ configuration_option.channel_mode =
+ DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
+ } else if (mode == RetransmissionFlowControlMode::ERTM) {
+ configuration_option.channel_mode =
+ DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION;
+ }
dynamic_channel_manager_->RegisterService(
- psm, {},
+ psm, configuration_option, {},
common::BindOnce(&L2capDynamicChannelHelper::on_l2cap_service_registration_complete,
common::Unretained(this)),
common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)), handler_);
}
void Connect(hci::Address address) {
+ // TODO: specify channel mode
dynamic_channel_manager_->ConnectChannel(
- address, psm_, common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)),
+ address, {}, psm_, common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)),
common::Bind(&L2capDynamicChannelHelper::on_connect_fail, common::Unretained(this)), handler_);
}
@@ -238,7 +249,7 @@
}
std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet) {
- auto packet_one = std::make_unique<packet::RawBuilder>();
+ auto packet_one = std::make_unique<packet::RawBuilder>(2000);
packet_one->AddOctets(packet);
channel_->GetQueueUpEnd()->UnregisterEnqueue();
return packet_one;
diff --git a/gd/l2cap/classic/facade.proto b/gd/l2cap/classic/facade.proto
index 21add63..7eb780d 100644
--- a/gd/l2cap/classic/facade.proto
+++ b/gd/l2cap/classic/facade.proto
@@ -30,9 +30,15 @@
facade.BluetoothAddress remote = 1;
}
+enum RetransmissionFlowControlMode {
+ BASIC = 0;
+ ERTM = 3;
+}
+
message OpenChannelRequest {
facade.BluetoothAddress remote = 1;
uint32 psm = 2;
+ RetransmissionFlowControlMode mode = 3;
}
message ConfigureChannelRequest {
@@ -78,6 +84,7 @@
message SetEnableDynamicChannelRequest {
uint32 psm = 1;
bool enable = 2;
+ RetransmissionFlowControlMode retransmission_mode = 3;
}
message DynamicChannelPacket {
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.cc b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
index bd56187..ba613a6 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.cc
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
@@ -19,6 +19,7 @@
#include "l2cap/cid.h"
#include "l2cap/classic/internal/dynamic_channel_impl.h"
#include "l2cap/classic/internal/link.h"
+#include "l2cap/internal/sender.h"
#include "l2cap/psm.h"
#include "l2cap/security_policy.h"
#include "os/handler.h"
@@ -97,6 +98,10 @@
incoming_configuration_status_ = status;
}
+void DynamicChannelImpl::SetSender(l2cap::internal::Sender* sender) {
+ sender_ = sender;
+}
+
Mtu DynamicChannelImpl::GetIncomingMtu() const {
return incoming_mtu_;
}
@@ -105,16 +110,9 @@
incoming_mtu_ = mtu;
}
-RetransmissionAndFlowControlModeOption DynamicChannelImpl::GetChannelMode() const {
- return mode_;
-}
-
-void DynamicChannelImpl::SetChannelMode(RetransmissionAndFlowControlModeOption mode) {
- mode_ = mode;
-}
-
-FcsType DynamicChannelImpl::GetFcsType() const {
- return fcs_type_;
+void DynamicChannelImpl::SetRetransmissionFlowControlConfig(
+ const RetransmissionAndFlowControlConfigurationOption& option) {
+ sender_->SetChannelRetransmissionFlowControlMode(option.mode_);
}
void DynamicChannelImpl::SetFcsType(FcsType fcs_type) {
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.h b/gd/l2cap/classic/internal/dynamic_channel_impl.h
index ba75814..ac1f02c 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.h
@@ -76,13 +76,17 @@
virtual ConfigurationStatus GetIncomingConfigurationStatus() const;
virtual void SetIncomingConfigurationStatus(ConfigurationStatus status);
+ /**
+ * Callback from the Scheduler to notify the Sender for this channel. On config update, channel might notify the
+ * configuration to Sender
+ */
+ void SetSender(l2cap::internal::Sender* sender) override;
+
virtual Mtu GetIncomingMtu() const;
virtual void SetIncomingMtu(Mtu mtu);
- virtual RetransmissionAndFlowControlModeOption GetChannelMode() const;
- virtual void SetChannelMode(RetransmissionAndFlowControlModeOption mode);
+ virtual void SetRetransmissionFlowControlConfig(const RetransmissionAndFlowControlConfigurationOption& mode);
- virtual FcsType GetFcsType() const;
virtual void SetFcsType(FcsType fcs_type);
// TODO(cmanton) Do something a little bit better than this
@@ -109,8 +113,8 @@
ConfigurationStatus outgoing_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
ConfigurationStatus incoming_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
+ l2cap::internal::Sender* sender_ = nullptr;
Mtu incoming_mtu_ = kDefaultClassicMtu;
- RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
// TODO: Add all RetransmissionAndFlowControlConfigurationOptions
FcsType fcs_type_ = FcsType::DEFAULT;
diff --git a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
index 57e5df4..2fcf3fc 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
@@ -19,6 +19,7 @@
#include "common/bind.h"
#include "l2cap/classic/dynamic_channel.h"
+#include "l2cap/classic/dynamic_channel_configuration_option.h"
#include "l2cap/classic/dynamic_channel_manager.h"
#include "l2cap/classic/dynamic_channel_service.h"
@@ -34,23 +35,31 @@
os::Handler* user_handler_ = nullptr;
DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete_callback_;
DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_;
+ DynamicChannelConfigurationOption configuration_;
};
virtual void NotifyChannelCreation(std::unique_ptr<DynamicChannel> channel) {
user_handler_->Post(common::BindOnce(on_connection_open_callback_, std::move(channel)));
}
+ DynamicChannelConfigurationOption GetConfigOption() const {
+ return config_option_;
+ }
+
friend class DynamicChannelServiceManagerImpl;
protected:
// protected access for mocking
DynamicChannelServiceImpl(os::Handler* user_handler,
- DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback)
- : user_handler_(user_handler), on_connection_open_callback_(std::move(on_connection_open_callback)) {}
+ DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback,
+ DynamicChannelConfigurationOption config_option)
+ : user_handler_(user_handler), on_connection_open_callback_(std::move(on_connection_open_callback)),
+ config_option_(config_option) {}
private:
os::Handler* user_handler_ = nullptr;
DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_;
+ DynamicChannelConfigurationOption config_option_;
};
} // namespace internal
diff --git a/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc b/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc
index d40bfae..a44a72e 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc
+++ b/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc
@@ -40,7 +40,8 @@
} else {
service_map_.try_emplace(psm,
DynamicChannelServiceImpl(pending_registration.user_handler_,
- std::move(pending_registration.on_connection_open_callback_)));
+ std::move(pending_registration.on_connection_open_callback_),
+ pending_registration.configuration_));
std::unique_ptr<DynamicChannelService> user_service(new DynamicChannelService(psm, this, l2cap_layer_handler_));
pending_registration.user_handler_->Post(
common::BindOnce(std::move(pending_registration.on_registration_complete_callback_),
diff --git a/gd/l2cap/classic/internal/fixed_channel_impl.cc b/gd/l2cap/classic/internal/fixed_channel_impl.cc
index 9bfaef8..8ac6c94 100644
--- a/gd/l2cap/classic/internal/fixed_channel_impl.cc
+++ b/gd/l2cap/classic/internal/fixed_channel_impl.cc
@@ -94,6 +94,8 @@
link_->RefreshRefCount();
}
+void FixedChannelImpl::SetSender(l2cap::internal::Sender* sender) {}
+
} // namespace internal
} // namespace classic
} // namespace l2cap
diff --git a/gd/l2cap/classic/internal/fixed_channel_impl.h b/gd/l2cap/classic/internal/fixed_channel_impl.h
index 563a770..6fde5c6 100644
--- a/gd/l2cap/classic/internal/fixed_channel_impl.h
+++ b/gd/l2cap/classic/internal/fixed_channel_impl.h
@@ -74,14 +74,7 @@
Cid GetRemoteCid() const {
return cid_;
}
-
- RetransmissionAndFlowControlModeOption GetChannelMode() const {
- return RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
- }
-
- void SetChannelMode(RetransmissionAndFlowControlModeOption) {
- LOG_ERROR("Setting channel mode on a fixed channel cid 0x%02hx", cid_);
- }
+ void SetSender(l2cap::internal::Sender* sender) override;
private:
// Constructor states
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index 055e77c..7b5178f 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -110,12 +110,10 @@
return channel;
}
-void Link::SetChannelRetransmissionFlowControlMode(Cid cid, RetransmissionAndFlowControlModeOption mode) {
- if (dynamic_channel_allocator_.FindChannelByCid(cid) == nullptr) {
- LOG_ERROR("Channel doesn't exist: %d", cid);
- return;
- }
- scheduler_->SetChannelRetransmissionFlowControlMode(cid, mode);
+classic::DynamicChannelConfigurationOption Link::GetConfigurationForInitialConfiguration(Cid cid) {
+ ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
+ local_cid_to_pending_dynamic_channel_connection_map_.end());
+ return local_cid_to_pending_dynamic_channel_connection_map_[cid].configuration_;
}
void Link::FreeDynamicChannel(Cid cid) {
@@ -139,12 +137,12 @@
}
}
-void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel) {
+void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel) {
ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
local_cid_to_pending_dynamic_channel_connection_map_.end());
auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid];
pending_dynamic_channel_connection.handler_->Post(
- common::BindOnce(std::move(pending_dynamic_channel_connection.on_open_callback_), std::move(channel)));
+ common::BindOnce(std::move(pending_dynamic_channel_connection.on_open_callback_), std::move(user_channel)));
local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
}
@@ -159,6 +157,30 @@
local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
}
+void Link::SetRemoteConnectionlessMtu(Mtu mtu) {
+ remote_mtu_ = mtu;
+}
+
+Mtu Link::GetRemoteConnectionlessMtu() const {
+ return remote_mtu_;
+}
+
+void Link::SetRemoteSupportsErtm(bool supported) {
+ remote_supports_ertm_ = supported;
+}
+
+bool Link::GetRemoteSupportsErtm() const {
+ return remote_supports_ertm_;
+}
+
+void Link::SetRemoteSupportsFcs(bool supported) {
+ remote_supports_fcs_ = supported;
+}
+
+bool Link::GetRemoteSupportsFcs() const {
+ return remote_supports_fcs_;
+}
+
} // namespace internal
} // namespace classic
} // namespace l2cap
diff --git a/gd/l2cap/classic/internal/link.h b/gd/l2cap/classic/internal/link.h
index f192e3e..2c6c1b8 100644
--- a/gd/l2cap/classic/internal/link.h
+++ b/gd/l2cap/classic/internal/link.h
@@ -20,6 +20,7 @@
#include <unordered_map>
#include "hci/acl_manager.h"
+#include "l2cap/classic/dynamic_channel_configuration_option.h"
#include "l2cap/classic/internal/dynamic_channel_allocator.h"
#include "l2cap/classic/internal/dynamic_channel_impl.h"
#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h"
@@ -55,6 +56,7 @@
os::Handler* handler_;
DynamicChannelManager::OnConnectionOpenCallback on_open_callback_;
DynamicChannelManager::OnConnectionFailureCallback on_fail_callback_;
+ classic::DynamicChannelConfigurationOption configuration_;
};
// ACL methods
@@ -87,7 +89,7 @@
virtual std::shared_ptr<DynamicChannelImpl> AllocateReservedDynamicChannel(Cid reserved_cid, Psm psm, Cid remote_cid,
SecurityPolicy security_policy);
- virtual void SetChannelRetransmissionFlowControlMode(Cid cid, RetransmissionAndFlowControlModeOption mode);
+ virtual classic::DynamicChannelConfigurationOption GetConfigurationForInitialConfiguration(Cid cid);
virtual void FreeDynamicChannel(Cid cid);
@@ -97,6 +99,14 @@
virtual void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel);
virtual void NotifyChannelFail(Cid cid);
+ // Information received from signalling channel
+ virtual void SetRemoteConnectionlessMtu(Mtu mtu);
+ virtual Mtu GetRemoteConnectionlessMtu() const;
+ virtual void SetRemoteSupportsErtm(bool supported);
+ virtual bool GetRemoteSupportsErtm() const;
+ virtual void SetRemoteSupportsFcs(bool supported);
+ virtual bool GetRemoteSupportsFcs() const;
+
private:
os::Handler* l2cap_handler_;
l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
@@ -110,6 +120,9 @@
ClassicSignallingManager signalling_manager_;
std::unordered_map<Cid, PendingDynamicChannelConnection> local_cid_to_pending_dynamic_channel_connection_map_;
os::Alarm link_idle_disconnect_alarm_{l2cap_handler_};
+ Mtu remote_mtu_ = kMinimumClassicMtu;
+ bool remote_supports_ertm_ = false;
+ bool remote_supports_fcs_ = false;
DISALLOW_COPY_AND_ASSIGN(Link);
};
diff --git a/gd/l2cap/classic/internal/signalling_manager.cc b/gd/l2cap/classic/internal/signalling_manager.cc
index 147a571..66a3f51 100644
--- a/gd/l2cap/classic/internal/signalling_manager.cc
+++ b/gd/l2cap/classic/internal/signalling_manager.cc
@@ -147,7 +147,39 @@
}
send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS,
ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
- SendConfigurationRequest(remote_cid, {});
+ auto* service = dynamic_service_manager_->GetService(psm);
+ auto initial_config = service->GetConfigOption();
+ if (!link_->GetRemoteSupportsErtm()) {
+ initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
+ }
+ auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
+ mtu_configuration->mtu_ = initial_config.incoming_mtu;
+ auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
+ fcs_option->fcs_type_ = FcsType::NO_FCS;
+ auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
+ switch (initial_config.channel_mode) {
+ case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
+ retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
+ break;
+ case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
+ retransmission_flow_control_configuration->mode_ =
+ RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
+ // TODO: Decide where to put initial values
+ retransmission_flow_control_configuration->tx_window_size_ = 10;
+ retransmission_flow_control_configuration->max_transmit_ = 20;
+ retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
+ retransmission_flow_control_configuration->monitor_time_out_ = 12000;
+ retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
+ break;
+ }
+
+ new_channel->SetRetransmissionFlowControlConfig(*retransmission_flow_control_configuration);
+ new_channel->SetIncomingMtu(initial_config.incoming_mtu);
+ std::vector<std::unique_ptr<ConfigurationOption>> config;
+ config.emplace_back(std::move(mtu_configuration));
+ config.emplace_back(std::move(retransmission_flow_control_configuration));
+ config.emplace_back(std::move(fcs_option));
+ SendConfigurationRequest(remote_cid, std::move(config));
}
void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
@@ -179,6 +211,33 @@
return;
}
alarm_.Cancel();
+ auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid());
+ if (!link_->GetRemoteSupportsErtm()) {
+ initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
+ }
+ auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
+ mtu_configuration->mtu_ = initial_config.incoming_mtu;
+ auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
+ switch (initial_config.channel_mode) {
+ case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
+ retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
+ break;
+ case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
+ retransmission_flow_control_configuration->mode_ =
+ RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
+ // TODO: Decide where to put initial values
+ retransmission_flow_control_configuration->tx_window_size_ = 10;
+ retransmission_flow_control_configuration->max_transmit_ = 20;
+ retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
+ retransmission_flow_control_configuration->monitor_time_out_ = 12000;
+ retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
+ break;
+ }
+ std::vector<std::unique_ptr<ConfigurationOption>> config;
+ config.emplace_back(std::move(mtu_configuration));
+ if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
+ config.emplace_back(std::move(retransmission_flow_control_configuration));
+ }
SendConfigurationRequest(remote_cid, {});
}
@@ -202,7 +261,7 @@
}
case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
- channel->SetChannelMode(config->mode_);
+ channel->SetRetransmissionFlowControlConfig(*config);
break;
}
case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
@@ -235,7 +294,7 @@
void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
ConfigurationResponseResult result,
- std::vector<std::unique_ptr<ConfigurationOption>> option) {
+ std::vector<std::unique_ptr<ConfigurationOption>> options) {
if (pending_commands_.empty()) {
LOG_WARN("Unexpected response: no pending request");
return;
@@ -250,6 +309,8 @@
handle_send_next_command();
return;
}
+
+ RetransmissionAndFlowControlConfigurationOption rfc_option;
channel->SetOutgoingConfigurationStatus(DynamicChannelImpl::ConfigurationStatus::CONFIGURED);
if (channel->GetIncomingConfigurationStatus() == DynamicChannelImpl::ConfigurationStatus::CONFIGURED) {
std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
@@ -331,15 +392,15 @@
void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) {
switch (type) {
case InformationRequestInfoType::CONNECTIONLESS_MTU: {
- auto response = InformationResponseConnectionlessMtuBuilder::Create(signal_id.Value(),
- InformationRequestResult::NOT_SUPPORTED, 0);
+ auto response = InformationResponseConnectionlessMtuBuilder::Create(
+ signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu);
enqueue_buffer_->Enqueue(std::move(response), handler_);
break;
}
case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
// TODO: implement this response
auto response = InformationResponseExtendedFeaturesBuilder::Create(
- signal_id.Value(), InformationRequestResult::NOT_SUPPORTED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0);
enqueue_buffer_->Enqueue(std::move(response), handler_);
break;
}
@@ -352,7 +413,7 @@
}
}
-void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) {
+void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
if (pending_commands_.empty()) {
LOG_WARN("Unexpected response: no pending request");
return;
@@ -364,7 +425,40 @@
last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) {
return;
}
- // TODO (hsz): Store the information response
+
+ auto type = response.GetInfoType();
+ switch (type) {
+ case InformationRequestInfoType::CONNECTIONLESS_MTU: {
+ auto view = InformationResponseConnectionlessMtuView::Create(response);
+ if (!view.IsValid()) {
+ LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
+ return;
+ }
+ link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
+ break;
+ }
+ case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
+ auto view = InformationResponseExtendedFeaturesView::Create(response);
+ if (!view.IsValid()) {
+ LOG_WARN("Invalid InformationResponseExtendedFeatures received");
+ return;
+ }
+ link_->SetRemoteSupportsErtm((view.GetEnhancedRetransmissionMode()));
+ link_->SetRemoteSupportsFcs(view.GetFcsOption());
+ // We don't care about other parameters
+ break;
+ }
+ case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
+ auto view = InformationResponseFixedChannelsView::Create(response);
+ if (!view.IsValid()) {
+ LOG_WARN("Invalid InformationResponseFixedChannel received");
+ return;
+ }
+ // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
+ break;
+ }
+ }
+
alarm_.Cancel();
handle_send_next_command();
}
diff --git a/gd/l2cap/classic/internal/signalling_manager.h b/gd/l2cap/classic/internal/signalling_manager.h
index 0ec6a28..0e17ec7 100644
--- a/gd/l2cap/classic/internal/signalling_manager.h
+++ b/gd/l2cap/classic/internal/signalling_manager.h
@@ -92,7 +92,7 @@
void OnInformationRequest(SignalId signal_id, InformationRequestInfoType type);
- void OnInformationResponse(SignalId signal_id, const InformationResponseView& view);
+ void OnInformationResponse(SignalId signal_id, const InformationResponseView& response);
private:
void on_incoming_packet();
diff --git a/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc b/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc
new file mode 100644
index 0000000..35c3002
--- /dev/null
+++ b/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc
@@ -0,0 +1,98 @@
+/*
+ * 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 "l2cap/internal/basic_mode_channel_data_controller.h"
+
+#include <gtest/gtest.h>
+
+#include "l2cap/internal/scheduler_mock.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace {
+
+std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) {
+ auto raw_builder = std::make_unique<packet::RawBuilder>();
+ raw_builder->AddOctets(payload);
+ return raw_builder;
+}
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ BitInserter i(*bytes);
+ bytes->reserve(packet->size());
+ packet->Serialize(i);
+ return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+void sync_handler(os::Handler* handler) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
+ auto status = future.wait_for(std::chrono::milliseconds(300));
+ EXPECT_EQ(status, std::future_status::ready);
+}
+
+class BasicModeDataControllerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
+ user_handler_ = new os::Handler(thread_);
+ queue_handler_ = new os::Handler(thread_);
+ }
+
+ void TearDown() override {
+ queue_handler_->Clear();
+ user_handler_->Clear();
+ delete queue_handler_;
+ delete user_handler_;
+ delete thread_;
+ }
+
+ os::Thread* thread_ = nullptr;
+ os::Handler* user_handler_ = nullptr;
+ os::Handler* queue_handler_ = nullptr;
+};
+
+TEST_F(BasicModeDataControllerTest, transmit) {
+ common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
+ testing::MockScheduler scheduler;
+ BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
+ controller.OnSdu(CreateSdu({1, 2, 3}));
+ auto next_packet = controller.GetNextPacket();
+ EXPECT_NE(next_packet, nullptr);
+}
+
+TEST_F(BasicModeDataControllerTest, receive) {
+ common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
+ testing::MockScheduler scheduler;
+ BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ auto base_view = GetPacketView(CreateSdu({0, 0, 1, 0}));
+ auto basic_frame_view = BasicFrameView::Create(base_view);
+ EXPECT_TRUE(basic_frame_view.IsValid());
+ controller.OnPdu(basic_frame_view);
+ sync_handler(queue_handler_);
+ auto packet_view = channel_queue.GetUpEnd()->TryDequeue();
+ EXPECT_NE(packet_view, nullptr);
+}
+
+} // namespace
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/internal/channel_impl.h b/gd/l2cap/internal/channel_impl.h
index 92f2bbb..ae17660 100644
--- a/gd/l2cap/internal/channel_impl.h
+++ b/gd/l2cap/internal/channel_impl.h
@@ -23,6 +23,7 @@
namespace bluetooth {
namespace l2cap {
namespace internal {
+class Sender;
/**
* Common interface for internal channel implementation
@@ -48,15 +49,11 @@
virtual Cid GetRemoteCid() const = 0;
/**
- * Return one of the supported channel mode as defined above
+ * Callback from the Scheduler to notify the Sender for this channel. On config update, channel might notify the
+ * configuration change to Sender.
+ * Fixed channel doesn't need to implement it, as it doesn't need to send config update to Sender.
*/
- virtual RetransmissionAndFlowControlModeOption GetChannelMode() const = 0;
-
- /**
- * Invoked by the command signalling manager to update the channel mode. Does NOT apply to fixed channel, OR LE
- * credit-based flow control channel
- */
- virtual void SetChannelMode(RetransmissionAndFlowControlModeOption) = 0;
+ virtual void SetSender(l2cap::internal::Sender* sender) = 0;
};
} // namespace internal
diff --git a/gd/l2cap/internal/channel_impl_mock.h b/gd/l2cap/internal/channel_impl_mock.h
index 0fe61e5..710e69a 100644
--- a/gd/l2cap/internal/channel_impl_mock.h
+++ b/gd/l2cap/internal/channel_impl_mock.h
@@ -34,8 +34,7 @@
GetQueueDownEnd, (), (override));
MOCK_METHOD(Cid, GetCid, (), (const, override));
MOCK_METHOD(Cid, GetRemoteCid, (), (const, override));
- MOCK_METHOD(RetransmissionAndFlowControlModeOption, GetChannelMode, (), (const, override));
- MOCK_METHOD(void, SetChannelMode, (RetransmissionAndFlowControlModeOption), (override));
+ MOCK_METHOD(void, SetSender, (l2cap::internal::Sender*), (override));
};
} // namespace testing
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
index ca4ca1f..3e5042d 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
@@ -76,8 +76,10 @@
bool local_busy_ = false;
int unacked_frames_ = 0;
// TODO: Instead of having a map, we may consider about a better data structure
- std::map<uint8_t, std::pair<SegmentationAndReassembly, CopyablePacketBuilder>> unacked_list_;
- std::queue<std::pair<SegmentationAndReassembly, std::unique_ptr<packet::BasePacketBuilder>>> pending_frames_;
+ // Map from TxSeq to (SAR, SDU size for START packet, information payload)
+ std::map<uint8_t, std::tuple<SegmentationAndReassembly, uint16_t, std::shared_ptr<packet::RawBuilder>>> unacked_list_;
+ // Stores (SAR, SDU size for START packet, information payload)
+ std::queue<std::tuple<SegmentationAndReassembly, uint16_t, std::unique_ptr<packet::RawBuilder>>> pending_frames_;
int retry_count_ = 0;
std::map<uint8_t /* tx_seq, */, int /* count */> retry_i_frames_;
bool rnr_sent_ = false;
@@ -92,13 +94,14 @@
// Events (@see 8.6.5.4)
- void data_request(SegmentationAndReassembly sar, std::unique_ptr<packet::BasePacketBuilder> pdu) {
+ void data_request(SegmentationAndReassembly sar, std::unique_ptr<packet::RawBuilder> pdu, uint16_t sdu_size = 0) {
+ // Note: sdu_size only applies to START packet
if (tx_state_ == TxState::XMIT && !remote_busy() && rem_window_not_full()) {
- send_data(sar, std::move(pdu));
+ send_data(sar, sdu_size, std::move(pdu));
} else if (tx_state_ == TxState::XMIT && (remote_busy() || rem_window_full())) {
- pend_data(sar, std::move(pdu));
+ pend_data(sar, sdu_size, std::move(pdu));
} else if (tx_state_ == TxState::WAIT_F) {
- pend_data(sar, std::move(pdu));
+ pend_data(sar, sdu_size, std::move(pdu));
}
}
@@ -487,11 +490,11 @@
}
bool with_valid_req_seq(uint8_t req_seq) {
- return expected_ack_seq_ <= req_seq && req_seq < next_tx_seq_;
+ return expected_ack_seq_ <= req_seq && req_seq <= next_tx_seq_;
}
bool with_valid_req_seq_retrans(uint8_t req_seq) {
- return expected_ack_seq_ <= req_seq && req_seq < next_tx_seq_;
+ return expected_ack_seq_ <= req_seq && req_seq <= next_tx_seq_;
}
bool with_valid_f_bit(Final f) {
@@ -550,18 +553,28 @@
// Actions (@see 8.6.5.6)
- void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<packet::BasePacketBuilder> segment, uint8_t req_seq,
- uint8_t tx_seq, Final f = Final::NOT_SET) {
- auto builder =
- ExtendedInformationFrameBuilder::Create(controller_->remote_cid_, f, req_seq, sar, tx_seq, std::move(segment));
+ void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<CopyablePacketBuilder> segment, uint8_t req_seq,
+ uint8_t tx_seq, uint16_t sdu_size = 0, Final f = Final::NOT_SET) {
+ std::unique_ptr<EnhancedInformationFrameBuilder> builder;
+ if (sar == SegmentationAndReassembly::START) {
+ builder = EnhancedInformationStartFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size,
+ std::move(segment));
+ } else {
+ builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar,
+ std::move(segment));
+ }
controller_->send_pdu(std::move(builder));
}
- void send_data(SegmentationAndReassembly sar, std::unique_ptr<packet::BasePacketBuilder> segment,
+ void send_data(SegmentationAndReassembly sar, uint16_t sdu_size, std::unique_ptr<packet::RawBuilder> segment,
Final f = Final::NOT_SET) {
+ std::shared_ptr<packet::RawBuilder> shared_segment(segment.release());
unacked_list_.emplace(std::piecewise_construct, std::forward_as_tuple(next_tx_seq_),
- std::forward_as_tuple(sar, std::move(segment)));
- _send_i_frame(sar, unacked_list_.find(next_tx_seq_)->second.second.Create(), buffer_seq_, next_tx_seq_, f);
+ std::forward_as_tuple(sar, sdu_size, shared_segment));
+
+ std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
+ std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(next_tx_seq_)->second));
+ _send_i_frame(sar, std::move(copyable_packet_builder), buffer_seq_, next_tx_seq_, sdu_size, f);
// TODO hsz fix me
unacked_frames_++;
frames_sent_++;
@@ -570,8 +583,8 @@
start_retrans_timer();
}
- void pend_data(SegmentationAndReassembly sar, std::unique_ptr<packet::BasePacketBuilder> data) {
- pending_frames_.emplace(std::make_pair(sar, std::move(data)));
+ void pend_data(SegmentationAndReassembly sar, uint16_t sdu_size, std::unique_ptr<packet::RawBuilder> data) {
+ pending_frames_.emplace(std::make_tuple(sar, sdu_size, std::move(data)));
}
void process_req_seq(uint8_t req_seq) {
@@ -702,8 +715,10 @@
uint8_t i = req_seq;
Final f = (p == Poll::NOT_SET ? Final::NOT_SET : Final::POLL_RESPONSE);
while (unacked_list_.find(i) == unacked_list_.end()) {
- _send_i_frame(unacked_list_.find(i)->second.first, unacked_list_.find(i)->second.second.Create(), buffer_seq_, i,
- f);
+ std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
+ std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(i)->second));
+ _send_i_frame(std::get<0>(unacked_list_.find(i)->second), std::move(copyable_packet_builder), buffer_seq_, i,
+ std::get<1>(unacked_list_.find(i)->second), f);
retry_i_frames_[i]++;
if (retry_i_frames_[i] == controller_->local_max_transmit_) {
CloseChannel();
@@ -720,8 +735,10 @@
LOG_ERROR("Received invalid SREJ");
return;
}
- _send_i_frame(unacked_list_.find(req_seq)->second.first, unacked_list_.find(req_seq)->second.second.Create(),
- buffer_seq_, req_seq, f);
+ std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
+ std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(req_seq)->second));
+ _send_i_frame(std::get<0>(unacked_list_.find(req_seq)->second), std::move(copyable_packet_builder), buffer_seq_,
+ req_seq, std::get<1>(unacked_list_.find(req_seq)->second), f);
retry_i_frames_[req_seq]++;
start_retrans_timer();
}
@@ -732,7 +749,7 @@
}
while (rem_window_not_full() && !pending_frames_.empty()) {
auto& frame = pending_frames_.front();
- send_data(frame.first, std::move(frame.second), f);
+ send_data(std::get<0>(frame), std::get<1>(frame), std::move(std::get<2>(frame)), f);
pending_frames_.pop();
f = Final::NOT_SET;
}
@@ -753,25 +770,24 @@
// Segmentation is handled here
void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) {
- LOG_ERROR("Not implemented");
// TODO: Optimize the calculation. We don't need to count for SDU length in CONTINUATION or END packets. We don't need
// to FCS when disabled.
- auto size_each_packet =
+ size_t size_each_packet =
(remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - 2 /* Extended control */ - 2 /* FCS */);
+ auto sdu_size = sdu->size();
std::vector<std::unique_ptr<packet::RawBuilder>> segments;
packet::FragmentingInserter fragmenting_inserter(size_each_packet, std::back_insert_iterator(segments));
sdu->Serialize(fragmenting_inserter);
+ fragmenting_inserter.finalize();
if (segments.size() == 1) {
- pimpl_->data_request(SegmentationAndReassembly::UNSEGMENTED, std::move(sdu));
+ pimpl_->data_request(SegmentationAndReassembly::UNSEGMENTED, std::move(segments[0]));
return;
}
- auto sar = SegmentationAndReassembly::START;
- for (auto i = 0; i < segments.size() - 1; i++) {
- pimpl_->data_request(sar, std::move(segments[i]));
- sar = SegmentationAndReassembly::CONTINUATION;
+ pimpl_->data_request(SegmentationAndReassembly::START, std::move(segments[0]), sdu_size);
+ for (auto i = 1; i < segments.size() - 1; i++) {
+ pimpl_->data_request(SegmentationAndReassembly::CONTINUATION, std::move(segments[i]));
}
- sar = SegmentationAndReassembly::END;
- pimpl_->data_request(sar, std::move(segments.back()));
+ pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back()));
}
void ErtmController::OnPdu(BasicFrameView pdu) {
@@ -876,10 +892,6 @@
builder_->Serialize(it);
}
-std::unique_ptr<BasePacketBuilder> ErtmController::CopyablePacketBuilder::Create() {
- return std::unique_ptr<packet::BasePacketBuilder>(builder_.get());
-}
-
} // namespace internal
} // namespace l2cap
} // namespace bluetooth
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
index 1e36f49..0566e0b 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
@@ -31,6 +31,7 @@
#include "os/queue.h"
#include "packet/base_packet_builder.h"
#include "packet/packet_view.h"
+#include "packet/raw_builder.h"
namespace bluetooth {
namespace l2cap {
@@ -62,7 +63,6 @@
class PacketViewForReassembly : public packet::PacketView<kLittleEndian> {
public:
PacketViewForReassembly(const PacketView& packetView) : PacketView(packetView) {}
- PacketViewForReassembly(nullptr_t) : PacketView(nullptr) {}
void AppendPacketView(packet::PacketView<kLittleEndian> to_append) {
Append(to_append);
}
@@ -70,19 +70,17 @@
class CopyablePacketBuilder : public packet::BasePacketBuilder {
public:
- CopyablePacketBuilder(std::unique_ptr<packet::BasePacketBuilder> builder) : builder_(builder.release()) {}
+ CopyablePacketBuilder(std::shared_ptr<packet::RawBuilder> builder) : builder_(std::move(builder)) {}
void Serialize(BitInserter& it) const override;
size_t size() const override;
- std::unique_ptr<packet::BasePacketBuilder> Create();
-
private:
- std::shared_ptr<packet::BasePacketBuilder> builder_;
+ std::shared_ptr<packet::RawBuilder> builder_;
};
- PacketViewForReassembly reassembly_stage_{nullptr};
+ PacketViewForReassembly reassembly_stage_{std::make_shared<std::vector<uint8_t>>()};
SegmentationAndReassembly sar_state_ = SegmentationAndReassembly::END;
void stage_for_reassembly(SegmentationAndReassembly sar, const packet::PacketView<kLittleEndian>& payload);
@@ -92,17 +90,13 @@
// Configuration options
// TODO: Configure these number
- [[maybe_unused]] uint16_t local_tx_window_ = 10;
- [[maybe_unused]] uint16_t local_max_transmit_ = 20;
- [[maybe_unused]] uint16_t local_retransmit_timeout_ms_ = 2000;
- [[maybe_unused]] uint16_t local_monitor_timeout_ms_ = 12000;
- [[maybe_unused]] uint16_t local_mps_ = 1010;
+ uint16_t local_tx_window_ = 10;
+ uint16_t local_max_transmit_ = 20;
+ uint16_t local_retransmit_timeout_ms_ = 2000;
+ uint16_t local_monitor_timeout_ms_ = 12000;
- [[maybe_unused]] uint16_t remote_tx_window_ = 10;
- [[maybe_unused]] uint16_t remote_max_transmit_ = 20;
- [[maybe_unused]] uint16_t remote_retransmit_timeout_ms_ = 2000;
- [[maybe_unused]] uint16_t remote_monitor_timeout_ms_ = 12000;
- [[maybe_unused]] uint16_t remote_mps_ = 1010;
+ uint16_t remote_tx_window_ = 10;
+ uint16_t remote_mps_ = 1010;
struct impl;
std::unique_ptr<impl> pimpl_;
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
new file mode 100644
index 0000000..dd87e36
--- /dev/null
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
@@ -0,0 +1,94 @@
+/*
+ * 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 "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h"
+
+#include <gtest/gtest.h>
+
+#include "l2cap/internal/scheduler_mock.h"
+#include "l2cap/l2cap_packets.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace {
+
+std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) {
+ auto raw_builder = std::make_unique<packet::RawBuilder>();
+ raw_builder->AddOctets(payload);
+ return raw_builder;
+}
+
+PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ BitInserter i(*bytes);
+ bytes->reserve(packet->size());
+ packet->Serialize(i);
+ return packet::PacketView<packet::kLittleEndian>(bytes);
+}
+
+void sync_handler(os::Handler* handler) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
+ auto status = future.wait_for(std::chrono::milliseconds(300));
+ EXPECT_EQ(status, std::future_status::ready);
+}
+
+class ErtmDataControllerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
+ user_handler_ = new os::Handler(thread_);
+ queue_handler_ = new os::Handler(thread_);
+ }
+
+ void TearDown() override {
+ queue_handler_->Clear();
+ user_handler_->Clear();
+ delete queue_handler_;
+ delete user_handler_;
+ delete thread_;
+ }
+
+ os::Thread* thread_ = nullptr;
+ os::Handler* user_handler_ = nullptr;
+ os::Handler* queue_handler_ = nullptr;
+};
+
+TEST_F(ErtmDataControllerTest, receive) {
+ common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
+ testing::MockScheduler scheduler;
+ ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ auto segment = CreateSdu({'a', 'b', 'c', 'd'});
+ auto builder = EnhancedInformationFrameBuilder::Create(1, 0, Final::NOT_SET, 0,
+ SegmentationAndReassembly::UNSEGMENTED, std::move(segment));
+ auto base_view = GetPacketView(std::move(builder));
+ auto basic_frame_view = BasicFrameView::Create(base_view);
+ EXPECT_TRUE(basic_frame_view.IsValid());
+ controller.OnPdu(basic_frame_view);
+ sync_handler(queue_handler_);
+ auto payload = channel_queue.GetUpEnd()->TryDequeue();
+ EXPECT_NE(payload, nullptr);
+ std::string data = std::string(payload->begin(), payload->end());
+ EXPECT_EQ(data, "abcd");
+}
+
+} // namespace
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/internal/scheduler.h b/gd/l2cap/internal/scheduler.h
index b7bd237..59f2bfd 100644
--- a/gd/l2cap/internal/scheduler.h
+++ b/gd/l2cap/internal/scheduler.h
@@ -20,6 +20,7 @@
#include "common/bidi_queue.h"
#include "l2cap/cid.h"
+#include "l2cap/classic/dynamic_channel_configuration_option.h"
#include "l2cap/internal/channel_impl.h"
#include "l2cap/internal/data_controller.h"
#include "l2cap/internal/sender.h"
@@ -50,6 +51,7 @@
/**
* Attach the channel with the specified ChannelQueueDownEnd into the scheduler.
+ * Scheduler needs to notify the channel its Sender through SetSender().
*
* @param cid The channel to attach to the scheduler.
* @param channel The reference to a DynamicChannelImpl object. Use nullptr for fixed channel.
@@ -70,11 +72,6 @@
virtual void OnPacketsReady(Cid cid, int number_packets) {}
/**
- * Set the channel mode for a cid
- */
- virtual void SetChannelRetransmissionFlowControlMode(Cid cid, RetransmissionAndFlowControlModeOption mode) {}
-
- /**
* Get the data controller for Reassembler
*/
virtual DataController* GetDataController(Cid cid) {
diff --git a/gd/l2cap/internal/scheduler_fifo.cc b/gd/l2cap/internal/scheduler_fifo.cc
index cd14f6f..7454cbe 100644
--- a/gd/l2cap/internal/scheduler_fifo.cc
+++ b/gd/l2cap/internal/scheduler_fifo.cc
@@ -40,6 +40,9 @@
ASSERT(sender_map_.find(cid) == sender_map_.end());
sender_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
std::forward_as_tuple(handler_, this, channel));
+ if (channel->GetCid() >= kFirstDynamicChannel) {
+ channel->SetSender(&sender_map_.find(cid)->second);
+ }
}
void Fifo::DetachChannel(Cid cid) {
@@ -79,11 +82,6 @@
link_queue_enqueue_registered_ = true;
}
-void Fifo::SetChannelRetransmissionFlowControlMode(Cid cid, RetransmissionAndFlowControlModeOption mode) {
- ASSERT(sender_map_.find(cid) != sender_map_.end());
- sender_map_.find(cid)->second.SetChannelRetransmissionFlowControlMode(mode);
-}
-
DataController* Fifo::GetDataController(Cid cid) {
if (sender_map_.find(cid) == sender_map_.end()) {
return nullptr;
diff --git a/gd/l2cap/internal/scheduler_fifo.h b/gd/l2cap/internal/scheduler_fifo.h
index ffbd086..b20ea4f 100644
--- a/gd/l2cap/internal/scheduler_fifo.h
+++ b/gd/l2cap/internal/scheduler_fifo.h
@@ -39,7 +39,6 @@
void AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel) override;
void DetachChannel(Cid cid) override;
void OnPacketsReady(Cid cid, int number_packets) override;
- void SetChannelRetransmissionFlowControlMode(Cid cid, RetransmissionAndFlowControlModeOption mode) override;
DataController* GetDataController(Cid cid) override;
private:
diff --git a/gd/l2cap/internal/scheduler_fifo_test.cc b/gd/l2cap/internal/scheduler_fifo_test.cc
index 3a53a36..ff78838 100644
--- a/gd/l2cap/internal/scheduler_fifo_test.cc
+++ b/gd/l2cap/internal/scheduler_fifo_test.cc
@@ -72,14 +72,10 @@
auto mock_channel_1 = std::make_shared<testing::MockChannelImpl>();
EXPECT_CALL(*mock_channel_1, GetQueueDownEnd()).WillRepeatedly(Return(channel_one_queue_.GetDownEnd()));
- EXPECT_CALL(*mock_channel_1, GetChannelMode())
- .WillRepeatedly(Return(RetransmissionAndFlowControlModeOption::L2CAP_BASIC));
EXPECT_CALL(*mock_channel_1, GetCid()).WillRepeatedly(Return(1));
EXPECT_CALL(*mock_channel_1, GetRemoteCid()).WillRepeatedly(Return(1));
auto mock_channel_2 = std::make_shared<testing::MockChannelImpl>();
EXPECT_CALL(*mock_channel_2, GetQueueDownEnd()).WillRepeatedly(Return(channel_two_queue_.GetDownEnd()));
- EXPECT_CALL(*mock_channel_2, GetChannelMode())
- .WillRepeatedly(Return(RetransmissionAndFlowControlModeOption::L2CAP_BASIC));
EXPECT_CALL(*mock_channel_2, GetCid()).WillRepeatedly(Return(2));
EXPECT_CALL(*mock_channel_2, GetRemoteCid()).WillRepeatedly(Return(2));
fifo_->AttachChannel(1, mock_channel_1);
diff --git a/gd/l2cap/internal/sender.cc b/gd/l2cap/internal/sender.cc
index 5296eff..ffe2755 100644
--- a/gd/l2cap/internal/sender.cc
+++ b/gd/l2cap/internal/sender.cc
@@ -59,7 +59,7 @@
if (mode_ == mode) {
return;
}
- if (mode_ == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
+ if (mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
data_controller_ =
std::make_unique<BasicModeDataController>(channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
return;
@@ -71,6 +71,10 @@
}
}
+void Sender::SetIncomingMtu(Mtu mtu) {
+ // TODO: Enforce MTU
+}
+
DataController* Sender::GetDataController() {
return data_controller_.get();
}
diff --git a/gd/l2cap/internal/sender.h b/gd/l2cap/internal/sender.h
index 8d3a72e..22f7737 100644
--- a/gd/l2cap/internal/sender.h
+++ b/gd/l2cap/internal/sender.h
@@ -25,6 +25,7 @@
#include "l2cap/cid.h"
#include "l2cap/internal/channel_impl.h"
#include "l2cap/internal/data_controller.h"
+#include "l2cap/mtu.h"
#include "os/handler.h"
#include "os/queue.h"
#include "packet/base_packet_builder.h"
@@ -61,6 +62,8 @@
void SetChannelRetransmissionFlowControlMode(RetransmissionAndFlowControlModeOption mode);
+ void SetIncomingMtu(Mtu mtu);
+
DataController* GetDataController();
private:
diff --git a/gd/l2cap/internal/sender_test.cc b/gd/l2cap/internal/sender_test.cc
index c3a913d..cb16245 100644
--- a/gd/l2cap/internal/sender_test.cc
+++ b/gd/l2cap/internal/sender_test.cc
@@ -67,8 +67,6 @@
queue_handler_ = new os::Handler(thread_);
mock_channel_ = std::make_shared<testing::MockChannelImpl>();
EXPECT_CALL(*mock_channel_, GetQueueDownEnd()).WillRepeatedly(Return(channel_queue_.GetDownEnd()));
- EXPECT_CALL(*mock_channel_, GetChannelMode())
- .WillRepeatedly(Return(RetransmissionAndFlowControlModeOption::L2CAP_BASIC));
EXPECT_CALL(*mock_channel_, GetCid()).WillRepeatedly(Return(0x41));
EXPECT_CALL(*mock_channel_, GetRemoteCid()).WillRepeatedly(Return(0x41));
sender_ = new Sender(queue_handler_, &scheduler_, mock_channel_);
diff --git a/gd/l2cap/l2cap_packets.pdl b/gd/l2cap/l2cap_packets.pdl
index ee9f3ed..ae44cb1 100644
--- a/gd/l2cap/l2cap_packets.pdl
+++ b/gd/l2cap/l2cap_packets.pdl
@@ -346,11 +346,11 @@
}
-struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL, length = 8) {
+struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL, length = 9) {
mode : RetransmissionAndFlowControlModeOption,
tx_window_size : 8, // 1-32 for Flow Control and Retransmission, 1-63 for Enhanced
max_transmit : 8,
- retransmission_time_out : 8,
+ retransmission_time_out : 16,
monitor_time_out : 16,
maximum_pdu_size : 16,
}
diff --git a/gd/l2cap/le/internal/fixed_channel_impl.cc b/gd/l2cap/le/internal/fixed_channel_impl.cc
index 5f85139..9ae4e1f 100644
--- a/gd/l2cap/le/internal/fixed_channel_impl.cc
+++ b/gd/l2cap/le/internal/fixed_channel_impl.cc
@@ -107,12 +107,10 @@
return cid_;
}
-RetransmissionAndFlowControlModeOption FixedChannelImpl::GetChannelMode() const {
- return RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
+void FixedChannelImpl::SetSender(l2cap::internal::Sender* sender) {
+ ASSERT_LOG(false, "Should not set sender for fixed channel");
}
-void FixedChannelImpl::SetChannelMode(RetransmissionAndFlowControlModeOption option) {}
-
} // namespace internal
} // namespace le
} // namespace l2cap
diff --git a/gd/l2cap/le/internal/fixed_channel_impl.h b/gd/l2cap/le/internal/fixed_channel_impl.h
index 972640e..82a4125 100644
--- a/gd/l2cap/le/internal/fixed_channel_impl.h
+++ b/gd/l2cap/le/internal/fixed_channel_impl.h
@@ -55,9 +55,7 @@
Cid GetCid() const override;
Cid GetRemoteCid() const override;
- RetransmissionAndFlowControlModeOption GetChannelMode() const override;
- void SetChannelMode(RetransmissionAndFlowControlModeOption option) override;
-
+ void SetSender(l2cap::internal::Sender* sender) override;
virtual void OnClosed(hci::ErrorCode status);
virtual std::string ToString() {
diff --git a/gd/packet/fragmenting_inserter.cc b/gd/packet/fragmenting_inserter.cc
index 3d8917c..90f87c6 100644
--- a/gd/packet/fragmenting_inserter.cc
+++ b/gd/packet/fragmenting_inserter.cc
@@ -23,7 +23,7 @@
FragmentingInserter::FragmentingInserter(size_t mtu,
std::back_insert_iterator<std::vector<std::unique_ptr<RawBuilder>>> iterator)
- : BitInserter(to_construct_bit_inserter_), mtu_(mtu), curr_packet_(std::make_unique<RawBuilder>()),
+ : BitInserter(to_construct_bit_inserter_), mtu_(mtu), curr_packet_(std::make_unique<RawBuilder>(mtu)),
iterator_(iterator) {}
void FragmentingInserter::insert_bits(uint8_t byte, size_t num_bits) {
@@ -36,7 +36,7 @@
curr_packet_->AddOctets1(new_byte);
if (curr_packet_->size() >= mtu_) {
iterator_ = std::move(curr_packet_);
- curr_packet_ = std::make_unique<RawBuilder>();
+ curr_packet_ = std::make_unique<RawBuilder>(mtu_);
}
total_bits -= 8;
new_value = new_value >> 8;
diff --git a/gd/packet/iterator.h b/gd/packet/iterator.h
index f15e561..8d927a0 100644
--- a/gd/packet/iterator.h
+++ b/gd/packet/iterator.h
@@ -18,6 +18,7 @@
#include <cstdint>
#include <forward_list>
+#include <memory>
#include "packet/view.h"
diff --git a/gd/packet/parser/main.cc b/gd/packet/parser/main.cc
index 05475b6..757523d 100644
--- a/gd/packet/parser/main.cc
+++ b/gd/packet/parser/main.cc
@@ -230,9 +230,16 @@
return true;
}
+// Get the out_file shard at a symbol_count
+std::ofstream& get_out_file(size_t symbol_count, size_t symbol_total, std::vector<std::ofstream>* out_files) {
+ auto symbols_per_shard = symbol_total / out_files->size();
+ auto file_index = std::min(symbol_count / symbols_per_shard, out_files->size() - 1);
+ return out_files->at(file_index);
+}
+
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) {
+ const std::string& root_namespace, size_t num_shards) {
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"));
@@ -241,85 +248,132 @@
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);
+ std::vector<std::ofstream> out_file_shards(num_shards);
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ auto filename = gen_path / (input_filename + "_python3_shard_" + std::to_string(i) + ".cc");
+ auto& out_file = out_file_shards[i];
+ out_file.open(filename);
+ if (!out_file.is_open()) {
+ std::cerr << "can't open " << filename << 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";
+
+ 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_shard_" << std::to_string(i) << "(py::module& m) {\n\n";
+ }
+ size_t symbol_total = 0;
+ // Only count types that will be generated
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ symbol_total++;
+ } else if (e.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
+ symbol_total++;
}
}
- 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";
+ // View and builder are counted separately
+ symbol_total += decls.packet_defs_queue_.size() * 2;
+ size_t symbol_count = 0;
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);
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
gen.GenDefinitionPybind11(out_file);
out_file << "\n\n";
+ symbol_count++;
}
}
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);
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
struct_def->GenDefinitionPybind11(out_file);
out_file << "\n";
+ symbol_count++;
}
}
for (const auto& packet_def : decls.packet_defs_queue_) {
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
packet_def.second.GenParserDefinitionPybind11(out_file);
out_file << "\n\n";
+ symbol_count++;
}
for (const auto& p : decls.packet_defs_queue_) {
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
p.second.GenBuilderDefinitionPybind11(out_file);
out_file << "\n\n";
+ symbol_count++;
}
- out_file << "}\n\n";
+ for (auto& out_file : out_file_shards) {
+ out_file << "}\n\n";
+ generate_namespace_close(namespace_list, out_file);
+ }
- generate_namespace_close(namespace_list, out_file);
+ auto gen_file_main = gen_path / (input_filename + "_python3.cc");
+ std::ofstream out_file_main;
+ out_file_main.open(gen_file_main);
+ if (!out_file_main.is_open()) {
+ std::cerr << "can't open " << gen_file_main << std::endl;
+ return false;
+ }
+ out_file_main << "#include <pybind11/pybind11.h>\n";
+ generate_namespace_open(namespace_list, out_file_main);
- out_file.close();
+ out_file_main << "namespace py = pybind11;\n\n";
+
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ out_file_main << "void define_" << input_filename << "_submodule_shard_" << std::to_string(i)
+ << "(py::module& m);\n";
+ }
+
+ out_file_main << "void define_" << input_filename << "_submodule(py::module& parent) {\n\n";
+ out_file_main << "py::module m = parent.def_submodule(\"" << input_filename << "\", \"A submodule of "
+ << input_filename << "\");\n\n";
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ out_file_main << "define_" << input_filename << "_submodule_shard_" << std::to_string(i) << "(m);\n";
+ }
+ out_file_main << "}\n\n";
+
+ generate_namespace_close(namespace_list, out_file_main);
return true;
}
@@ -335,10 +389,13 @@
std::filesystem::path out_dir;
std::filesystem::path include_dir;
std::string root_namespace = "bluetooth";
+ // Number of shards per output pybind11 cc file
+ size_t num_shards = 1;
std::queue<std::filesystem::path> input_files;
const std::string arg_out = "--out=";
const std::string arg_include = "--include=";
const std::string arg_namespace = "--root_namespace=";
+ const std::string arg_num_shards = "--num_shards=";
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
@@ -348,12 +405,15 @@
include_dir = std::filesystem::current_path() / std::filesystem::path(arg.substr(arg_include.size()));
} else if (arg.find(arg_namespace) == 0) {
root_namespace = arg.substr(arg_namespace.size());
+ } else if (arg.find(arg_num_shards) == 0) {
+ num_shards = std::stoul(arg.substr(arg_num_shards.size()));
} else {
input_files.emplace(std::filesystem::current_path() / std::filesystem::path(arg));
}
}
- if (out_dir == std::filesystem::path() || include_dir == std::filesystem::path()) {
- std::cerr << "Usage: bt-packetgen --out=OUT --include=INCLUDE --root=NAMESPACE input_files..." << std::endl;
+ if (out_dir == std::filesystem::path() || include_dir == std::filesystem::path() || num_shards == 0) {
+ std::cerr << "Usage: bt-packetgen --out=OUT --include=INCLUDE --root_namespace=NAMESPACE --num_shards=NUM_SHARDS "
+ << "input_files..." << std::endl;
return 1;
}
@@ -367,7 +427,8 @@
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)) {
+ if (!generate_pybind11_sources_one_file(declarations, input_files.front(), include_dir, out_dir, root_namespace,
+ num_shards)) {
std::cerr << "Didn't generate pybind11 sources for " << input_files.front() << std::endl;
return 4;
}
diff --git a/gd/packet/view.h b/gd/packet/view.h
index 4f3b508..3b8b679 100644
--- a/gd/packet/view.h
+++ b/gd/packet/view.h
@@ -17,6 +17,7 @@
#pragma once
#include <cstdint>
+#include <memory>
#include <vector>
namespace bluetooth {
diff --git a/gd/shim/l2cap.cc b/gd/shim/l2cap.cc
index 6177272..d703972 100644
--- a/gd/shim/l2cap.cc
+++ b/gd/shim/l2cap.cc
@@ -396,11 +396,13 @@
std::make_shared<ServiceInterface>(&connection_interface_manager_, psm, on_open, std::move(completed));
psm_to_service_interface_map_.emplace(psm, service_interface);
+ // TODO(cmanton): Use the configuration option from user
service_interface->RegisterService(
[this](l2cap::Psm psm, l2cap::SecurityPolicy security_policy,
l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open) {
- bool rc = dynamic_channel_manager_->RegisterService(psm, security_policy, std::move(on_registration_complete),
+ bool rc = dynamic_channel_manager_->RegisterService(psm, l2cap::classic::DynamicChannelConfigurationOption(),
+ security_policy, std::move(on_registration_complete),
on_connection_open, handler_);
ASSERT_LOG(rc == true, "Failed to register classic service");
});
@@ -418,9 +420,10 @@
// TODO(cmanton) hash psm/address pair into unordered map for pending_connection
// This is ok for now
psm_to_pending_connection_map_[psm] = pending_connection;
-
+ // TODO(cmanton): Add ERTM mode support by changing configuratio_option in ConnectChannel()
bool rc = dynamic_channel_manager_->ConnectChannel(
- address, psm, common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
+ address, l2cap::classic::DynamicChannelConfigurationOption(), psm,
+ common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
common::BindOnce(&PendingConnection::OnConnectionFailure, common::Unretained(pending_connection.get())),
handler_);
ASSERT_LOG(rc == true, "Failed to create classic connection");
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
index c1fcd84..014015a 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -42,19 +42,25 @@
return unused_handle;
}
-bool AclConnectionHandler::CreatePendingConnection(Address addr) {
+bool AclConnectionHandler::CreatePendingConnection(
+ Address addr, bool authenticate_on_connect) {
if (classic_connection_pending_) {
return false;
}
classic_connection_pending_ = true;
pending_connection_address_ = addr;
+ authenticate_pending_classic_connection_ = authenticate_on_connect;
return true;
}
-bool AclConnectionHandler::HasPendingConnection(Address addr) {
+bool AclConnectionHandler::HasPendingConnection(Address addr) const {
return classic_connection_pending_ && pending_connection_address_ == addr;
}
+bool AclConnectionHandler::AuthenticatePendingConnection() const {
+ return authenticate_pending_classic_connection_;
+}
+
bool AclConnectionHandler::CancelPendingConnection(Address addr) {
if (!classic_connection_pending_ || pending_connection_address_ != addr) {
return false;
@@ -79,7 +85,8 @@
return true;
}
-bool AclConnectionHandler::HasPendingLeConnection(Address addr, uint8_t address_type) {
+bool AclConnectionHandler::HasPendingLeConnection(Address addr,
+ uint8_t address_type) const {
return le_connection_pending_ && pending_le_connection_address_ == addr &&
pending_le_connection_address_type_ == address_type;
}
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
index 6b32952..c08f529 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -34,12 +34,13 @@
virtual ~AclConnectionHandler() = default;
- bool CreatePendingConnection(Address addr);
- bool HasPendingConnection(Address addr);
+ bool CreatePendingConnection(Address addr, bool authenticate_on_connect);
+ bool HasPendingConnection(Address addr) const;
bool CancelPendingConnection(Address addr);
+ bool AuthenticatePendingConnection() const;
bool CreatePendingLeConnection(Address addr, uint8_t addr_type);
- bool HasPendingLeConnection(Address addr, uint8_t addr_type);
+ bool HasPendingLeConnection(Address addr, uint8_t addr_type) const;
bool CancelPendingLeConnection(Address addr, uint8_t addr_type);
uint16_t CreateConnection(Address addr);
@@ -65,10 +66,12 @@
private:
std::unordered_map<uint16_t, AclConnection> acl_connections_;
bool classic_connection_pending_{false};
- Address pending_connection_address_;
+ Address pending_connection_address_{Address::kEmpty};
+ bool authenticate_pending_classic_connection_{false};
bool le_connection_pending_{false};
- Address pending_le_connection_address_;
- uint8_t pending_le_connection_address_type_;
+ Address pending_le_connection_address_{Address::kEmpty};
+ uint8_t pending_le_connection_address_type_{false};
+
uint16_t GetUnusedHandle();
uint16_t last_handle_{acl::kReservedHandle - 2};
void set_own_address_type(uint16_t handle, uint8_t own_address_type);
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 bc48af9..75b87b0 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
@@ -26,9 +26,8 @@
#include "packet/raw_builder.h"
#include "hci.h"
-#include "packets/hci/acl_packet_view.h"
#include "packets/hci/command_packet_view.h"
-#include "packets/hci/sco_packet_view.h"
+#include "packets/packet_view.h"
using std::vector;
using test_vendor_lib::hci::EventCode;
@@ -50,6 +49,7 @@
namespace test_vendor_lib {
constexpr char DualModeController::kControllerPropertiesFile[];
constexpr uint16_t DualModeController::kSecurityManagerNumKeys;
+constexpr uint16_t kNumCommandPackets = 0x01;
// Device methods.
void DualModeController::Initialize(const std::vector<std::string>& args) {
@@ -76,16 +76,10 @@
link_layer_controller_.TimerTick();
}
-void DualModeController::SendCommandCompleteSuccess(
- bluetooth::hci::OpCode command_opcode) const {
- SendCommandCompleteOnlyStatus(command_opcode,
- bluetooth::hci::ErrorCode::SUCCESS);
-}
-
void DualModeController::SendCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode) const {
std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(0x01); // num_responses
+ raw_builder_ptr->AddOctets1(kNumCommandPackets);
raw_builder_ptr->AddOctets2(command_opcode);
raw_builder_ptr->AddOctets1(
static_cast<uint8_t>(bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND));
@@ -95,32 +89,6 @@
send_event_(std::move(packet));
}
-void DualModeController::SendCommandCompleteOnlyStatus(
- bluetooth::hci::OpCode command_opcode,
- bluetooth::hci::ErrorCode status) const {
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(static_cast<uint8_t>(status));
- auto packet = bluetooth::hci::CommandCompleteBuilder::Create(
- 0x01, command_opcode, std::move(raw_builder_ptr));
- send_event_(std::move(packet));
-}
-
-void DualModeController::SendCommandStatus(
- bluetooth::hci::ErrorCode status,
- bluetooth::hci::OpCode command_opcode) const {
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- auto packet = bluetooth::hci::CommandStatusBuilder::Create(
- status, 0x01, command_opcode, std::move(raw_builder_ptr));
- send_event_(std::move(packet));
-}
-
-void DualModeController::SendCommandStatusSuccess(
- bluetooth::hci::OpCode command_opcode) const {
- SendCommandStatus(bluetooth::hci::ErrorCode::SUCCESS, command_opcode);
-}
-
DualModeController::DualModeController(const std::string& properties_filename, uint16_t num_keys)
: Device(properties_filename), security_manager_(num_keys) {
loopback_mode_ = hci::LoopbackMode::NO;
@@ -159,7 +127,7 @@
SET_HANDLER(OpCode::WRITE_SIMPLE_PAIRING_MODE, HciWriteSimplePairingMode);
SET_HANDLER(OpCode::WRITE_LE_HOST_SUPPORT, HciWriteLeHostSupport);
SET_HANDLER(OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT,
- HciWriteSecureConnectionHostSupport);
+ HciWriteSecureConnectionsHostSupport);
SET_HANDLER(OpCode::SET_EVENT_MASK, HciSetEventMask);
SET_HANDLER(OpCode::WRITE_INQUIRY_MODE, HciWriteInquiryMode);
SET_HANDLER(OpCode::WRITE_PAGE_SCAN_TYPE, HciWritePageScanType);
@@ -245,7 +213,7 @@
uint16_t handle = args.begin().extract<uint16_t>();
auto packet = bluetooth::hci::SniffSubratingCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, handle);
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, handle);
send_event_(std::move(packet));
}
@@ -265,19 +233,19 @@
}
void DualModeController::HandleAcl(std::shared_ptr<std::vector<uint8_t>> packet) {
- auto acl_packet = packets::AclPacketView::Create(packet);
+ bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian> raw_packet(packet);
+ auto acl_packet = bluetooth::hci::AclPacketView::Create(raw_packet);
+ ASSERT(acl_packet.IsValid());
if (loopback_mode_ == hci::LoopbackMode::LOCAL) {
uint16_t handle = acl_packet.GetHandle();
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(0x01);
- raw_builder_ptr->AddOctets2(handle);
- raw_builder_ptr->AddOctets2(0x01);
-
- auto packet = bluetooth::hci::EventPacketBuilder::Create(
- bluetooth::hci::EventCode::NUMBER_OF_COMPLETED_PACKETS,
- std::move(raw_builder_ptr));
+ std::vector<bluetooth::hci::CompletedPackets> completed_packets;
+ bluetooth::hci::CompletedPackets cp;
+ cp.connection_handle_ = handle;
+ cp.host_num_of_completed_packets_ = kNumCommandPackets;
+ completed_packets.push_back(cp);
+ auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
+ completed_packets);
send_event_(std::move(packet));
return;
}
@@ -286,19 +254,18 @@
}
void DualModeController::HandleSco(std::shared_ptr<std::vector<uint8_t>> packet) {
- auto sco_packet = packets::ScoPacketView::Create(packet);
+ bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian> raw_packet(packet);
+ auto sco_packet = bluetooth::hci::ScoPacketView::Create(raw_packet);
if (loopback_mode_ == hci::LoopbackMode::LOCAL) {
uint16_t handle = sco_packet.GetHandle();
send_sco_(packet);
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(0x01);
- raw_builder_ptr->AddOctets2(handle);
- raw_builder_ptr->AddOctets2(0x01);
-
- auto packet = bluetooth::hci::EventPacketBuilder::Create(
- bluetooth::hci::EventCode::NUMBER_OF_COMPLETED_PACKETS,
- std::move(raw_builder_ptr));
+ std::vector<bluetooth::hci::CompletedPackets> completed_packets;
+ bluetooth::hci::CompletedPackets cp;
+ cp.connection_handle_ = handle;
+ cp.host_num_of_completed_packets_ = kNumCommandPackets;
+ completed_packets.push_back(cp);
+ auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
+ completed_packets);
send_event_(std::move(packet));
return;
}
@@ -349,8 +316,15 @@
void DualModeController::RegisterAclChannel(
const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
- link_layer_controller_.RegisterAclChannel(callback);
- send_acl_ = callback;
+ send_acl_ =
+ [callback](std::shared_ptr<bluetooth::hci::AclPacketBuilder> acl_data) {
+ auto bytes = std::make_shared<std::vector<uint8_t>>();
+ bluetooth::packet::BitInserter bit_inserter(*bytes);
+ bytes->reserve(acl_data->size());
+ acl_data->Serialize(bit_inserter);
+ callback(std::move(bytes));
+ };
+ link_layer_controller_.RegisterAclChannel(send_acl_);
}
void DualModeController::RegisterScoChannel(
@@ -373,14 +347,15 @@
loopback_mode_ = hci::LoopbackMode::NO;
}
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::RESET);
+ send_event_(bluetooth::hci::ResetCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS));
}
void DualModeController::HciReadBufferSize(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::ReadBufferSizeCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetAclDataPacketSize(),
properties_.GetSynchronousDataPacketSize(),
properties_.GetTotalNumAclDataPackets(),
@@ -395,32 +370,34 @@
uint16_t handle = args.begin().extract<uint16_t>();
auto packet = bluetooth::hci::ReadEncryptionKeySizeCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, handle,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, handle,
properties_.GetEncryptionKeySize());
send_event_(std::move(packet));
}
void DualModeController::HciHostBufferSize(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 7, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::HOST_BUFFER_SIZE);
+ auto packet = bluetooth::hci::HostBufferSizeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciReadLocalVersionInformation(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets1(properties_.GetVersion());
- raw_builder_ptr->AddOctets2(properties_.GetRevision());
- raw_builder_ptr->AddOctets1(properties_.GetLmpPalVersion());
- raw_builder_ptr->AddOctets2(properties_.GetManufacturerName());
- raw_builder_ptr->AddOctets2(properties_.GetLmpPalSubversion());
-
- auto packet = bluetooth::hci::CommandCompleteBuilder::Create(
- 0x01, bluetooth::hci::OpCode::READ_LOCAL_VERSION_INFORMATION,
- std::move(raw_builder_ptr));
+ bluetooth::hci::LocalVersionInformation local_version_information;
+ local_version_information.hci_version_ =
+ static_cast<bluetooth::hci::HciVersion>(properties_.GetVersion());
+ local_version_information.hci_revision_ = properties_.GetRevision();
+ local_version_information.lmp_version_ =
+ static_cast<bluetooth::hci::LmpVersion>(properties_.GetLmpPalVersion());
+ local_version_information.manufacturer_name_ =
+ properties_.GetManufacturerName();
+ local_version_information.lmp_subversion_ = properties_.GetLmpPalSubversion();
+ auto packet =
+ bluetooth::hci::ReadLocalVersionInformationCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
+ local_version_information);
send_event_(std::move(packet));
}
@@ -432,14 +409,17 @@
auto status = link_layer_controller_.SendCommandToRemoteByHandle(
bluetooth::hci::OpCode::READ_REMOTE_VERSION_INFORMATION, args, handle);
- SendCommandStatus(status,
- bluetooth::hci::OpCode::READ_REMOTE_VERSION_INFORMATION);
+ auto packet =
+ bluetooth::hci::ReadRemoteVersionInformationStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciReadBdAddr(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::ReadBdAddrCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, properties_.GetAddress());
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
+ properties_.GetAddress());
send_event_(std::move(packet));
}
@@ -457,7 +437,8 @@
auto packet =
bluetooth::hci::ReadLocalSupportedCommandsCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, supported_commands);
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
+ supported_commands);
send_event_(std::move(packet));
}
@@ -465,7 +446,7 @@
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet =
bluetooth::hci::ReadLocalSupportedFeaturesCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetSupportedFeatures());
send_event_(std::move(packet));
}
@@ -473,7 +454,7 @@
void DualModeController::HciReadLocalSupportedCodecs(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::ReadLocalSupportedCodecsCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetSupportedCodecs(), properties_.GetVendorSpecificCodecs());
send_event_(std::move(packet));
}
@@ -484,7 +465,7 @@
auto pakcet =
bluetooth::hci::ReadLocalExtendedFeaturesCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, page_number,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, page_number,
properties_.GetExtendedFeaturesMaximumPageNumber(),
properties_.GetExtendedFeatures(page_number));
send_event_(std::move(pakcet));
@@ -498,8 +479,9 @@
auto status = link_layer_controller_.SendCommandToRemoteByHandle(
bluetooth::hci::OpCode::READ_REMOTE_EXTENDED_FEATURES, args, handle);
- SendCommandStatus(status,
- bluetooth::hci::OpCode::READ_REMOTE_EXTENDED_FEATURES);
+ auto packet = bluetooth::hci::ReadRemoteExtendedFeaturesStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciSwitchRole(packets::PacketView<true> args) {
@@ -510,7 +492,9 @@
auto status = link_layer_controller_.SwitchRole(address, role);
- SendCommandStatus(status, bluetooth::hci::OpCode::SWITCH_ROLE);
+ auto packet = bluetooth::hci::SwitchRoleStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciReadRemoteSupportedFeatures(packets::PacketView<true> args) {
@@ -521,8 +505,10 @@
auto status = link_layer_controller_.SendCommandToRemoteByHandle(
bluetooth::hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES, args, handle);
- SendCommandStatus(status,
- bluetooth::hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES);
+ auto packet =
+ bluetooth::hci::ReadRemoteSupportedFeaturesStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciReadClockOffset(packets::PacketView<true> args) {
@@ -533,7 +519,9 @@
auto status = link_layer_controller_.SendCommandToRemoteByHandle(
bluetooth::hci::OpCode::READ_CLOCK_OFFSET, args, handle);
- SendCommandStatus(status, bluetooth::hci::OpCode::READ_CLOCK_OFFSET);
+ auto packet = bluetooth::hci::ReadClockOffsetStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciIoCapabilityRequestReply(packets::PacketView<true> args) {
@@ -548,7 +536,7 @@
auto status = link_layer_controller_.IoCapabilityRequestReply(
peer, io_capability, oob_data_present_flag, authentication_requirements);
auto packet = bluetooth::hci::IoCapabilityRequestReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -561,7 +549,7 @@
auto status = link_layer_controller_.UserConfirmationRequestReply(peer);
auto packet =
bluetooth::hci::UserConfirmationRequestReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -575,7 +563,7 @@
link_layer_controller_.UserConfirmationRequestNegativeReply(peer);
auto packet =
bluetooth::hci::UserConfirmationRequestNegativeReplyCompleteBuilder::
- Create(0x01, status, peer);
+ Create(kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -590,7 +578,7 @@
auto status =
link_layer_controller_.UserPasskeyRequestReply(peer, numeric_value);
auto packet = bluetooth::hci::UserPasskeyRequestReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -603,7 +591,7 @@
auto status = link_layer_controller_.UserPasskeyRequestNegativeReply(peer);
auto packet =
bluetooth::hci::UserPasskeyRequestNegativeReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -624,7 +612,7 @@
auto status = link_layer_controller_.RemoteOobDataRequestReply(peer, c, r);
auto packet =
bluetooth::hci::RemoteOobDataRequestReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -637,7 +625,7 @@
auto status = link_layer_controller_.RemoteOobDataRequestNegativeReply(peer);
auto packet =
bluetooth::hci::RemoteOobDataRequestNegativeReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -653,7 +641,7 @@
link_layer_controller_.IoCapabilityRequestNegativeReply(peer, reason);
auto packet =
bluetooth::hci::IoCapabilityRequestNegativeReplyCompleteBuilder::Create(
- 0x01, status, peer);
+ kNumCommandPackets, status, peer);
send_event_(std::move(packet));
}
@@ -662,7 +650,9 @@
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
ASSERT(args[0] == 1 || args[0] == 0);
link_layer_controller_.WriteSimplePairingMode(args[0] == 1);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_SIMPLE_PAIRING_MODE);
+ auto packet = bluetooth::hci::WriteSimplePairingModeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciChangeConnectionPacketType(packets::PacketView<true> args) {
@@ -674,42 +664,55 @@
auto status =
link_layer_controller_.ChangeConnectionPacketType(handle, packet_type);
- SendCommandStatus(status,
- bluetooth::hci::OpCode::CHANGE_CONNECTION_PACKET_TYPE);
+ auto packet = bluetooth::hci::ChangeConnectionPacketTypeStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteLeHostSupport(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_LE_HOST_SUPPORT);
+ auto packet = bluetooth::hci::WriteLeHostSupportCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
-void DualModeController::HciWriteSecureConnectionHostSupport(
+void DualModeController::HciWriteSecureConnectionsHostSupport(
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);
+ auto packet =
+ bluetooth::hci::WriteSecureConnectionsHostSupportCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciSetEventMask(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 8, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::SET_EVENT_MASK);
+ auto packet = bluetooth::hci::SetEventMaskCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteInquiryMode(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
link_layer_controller_.SetInquiryMode(args[0]);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_INQUIRY_MODE);
+ auto packet = bluetooth::hci::WriteInquiryModeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWritePageScanType(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_PAGE_SCAN_TYPE);
+ auto packet = bluetooth::hci::WritePageScanTypeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteInquiryScanType(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_INQUIRY_SCAN_TYPE);
+ auto packet = bluetooth::hci::WriteInquiryScanTypeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciAuthenticationRequested(packets::PacketView<true> args) {
@@ -717,7 +720,9 @@
uint16_t handle = args.begin().extract<uint16_t>();
auto status = link_layer_controller_.AuthenticationRequested(handle);
- SendCommandStatus(status, bluetooth::hci::OpCode::AUTHENTICATION_REQUESTED);
+ auto packet = bluetooth::hci::AuthenticationRequestedStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciSetConnectionEncryption(packets::PacketView<true> args) {
@@ -728,7 +733,9 @@
auto status =
link_layer_controller_.SetConnectionEncryption(handle, encryption_enable);
- SendCommandStatus(status, bluetooth::hci::OpCode::SET_CONNECTION_ENCRYPTION);
+ auto packet = bluetooth::hci::SetConnectionEncryptionStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciChangeConnectionLinkKey(packets::PacketView<true> args) {
@@ -738,7 +745,9 @@
auto status = link_layer_controller_.ChangeConnectionLinkKey(handle);
- SendCommandStatus(status, bluetooth::hci::OpCode::CHANGE_CONNECTION_LINK_KEY);
+ auto packet = bluetooth::hci::ChangeConnectionLinkKeyStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciMasterLinkKey(packets::PacketView<true> args) {
@@ -748,20 +757,24 @@
auto status = link_layer_controller_.MasterLinkKey(key_flag);
- SendCommandStatus(status, bluetooth::hci::OpCode::MASTER_LINK_KEY);
+ auto packet = bluetooth::hci::MasterLinkKeyStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteAuthenticationEnable(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
properties_.SetAuthenticationEnable(args[0]);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::WRITE_AUTHENTICATION_ENABLE);
+ auto packet =
+ bluetooth::hci::WriteAuthenticationEnableCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciReadAuthenticationEnable(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::ReadAuthenticationEnableCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
static_cast<bluetooth::hci::AuthenticationEnable>(
properties_.GetAuthenticationEnable()));
send_event_(std::move(packet));
@@ -770,12 +783,16 @@
void DualModeController::HciWriteClassOfDevice(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 3, "%s size=%zu", __func__, args.size());
properties_.SetClassOfDevice(args[0], args[1], args[2]);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_CLASS_OF_DEVICE);
+ auto packet = bluetooth::hci::WriteClassOfDeviceCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWritePageTimeout(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_PAGE_TIMEOUT);
+ auto packet = bluetooth::hci::WritePageTimeoutCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciHoldMode(packets::PacketView<true> args) {
@@ -788,7 +805,9 @@
auto status = link_layer_controller_.HoldMode(handle, hold_mode_max_interval,
hold_mode_min_interval);
- SendCommandStatus(status, bluetooth::hci::OpCode::HOLD_MODE);
+ auto packet =
+ bluetooth::hci::HoldModeStatusBuilder::Create(status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciSniffMode(packets::PacketView<true> args) {
@@ -804,7 +823,9 @@
sniff_min_interval,
sniff_attempt, sniff_timeout);
- SendCommandStatus(status, bluetooth::hci::OpCode::SNIFF_MODE);
+ auto packet = bluetooth::hci::SniffModeStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciExitSniffMode(packets::PacketView<true> args) {
@@ -814,7 +835,9 @@
auto status = link_layer_controller_.ExitSniffMode(handle);
- SendCommandStatus(status, bluetooth::hci::OpCode::EXIT_SNIFF_MODE);
+ auto packet = bluetooth::hci::ExitSniffModeStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciQosSetup(packets::PacketView<true> args) {
@@ -832,13 +855,17 @@
link_layer_controller_.QosSetup(handle, service_type, token_rate,
peak_bandwidth, latency, delay_variation);
- SendCommandStatus(status, bluetooth::hci::OpCode::QOS_SETUP);
+ auto packet =
+ bluetooth::hci::QosSetupStatusBuilder::Create(status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteDefaultLinkPolicySettings(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS);
+ auto packet =
+ bluetooth::hci::WriteDefaultLinkPolicySettingsCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciFlowSpecification(packets::PacketView<true> args) {
@@ -857,7 +884,9 @@
handle, flow_direction, service_type, token_rate, token_bucket_size,
peak_bandwidth, access_latency);
- SendCommandStatus(status, bluetooth::hci::OpCode::FLOW_SPECIFICATION);
+ auto packet = bluetooth::hci::FlowSpecificationStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteLinkPolicySettings(packets::PacketView<true> args) {
@@ -871,7 +900,7 @@
link_layer_controller_.WriteLinkPolicySettings(handle, settings);
auto packet = bluetooth::hci::WriteLinkPolicySettingsCompleteBuilder::Create(
- 0x01, status, handle);
+ kNumCommandPackets, status, handle);
send_event_(std::move(packet));
}
@@ -886,7 +915,7 @@
link_layer_controller_.WriteLinkSupervisionTimeout(handle, timeout);
auto packet =
bluetooth::hci::WriteLinkSupervisionTimeoutCompleteBuilder::Create(
- 0x01, status, handle);
+ kNumCommandPackets, status, handle);
send_event_(std::move(packet));
}
@@ -902,7 +931,7 @@
std::copy_n(properties_.GetName().begin(), len, local_name.begin());
auto packet = bluetooth::hci::ReadLocalNameCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, local_name);
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, local_name);
send_event_(std::move(packet));
}
@@ -910,7 +939,9 @@
ASSERT_LOG(args.size() == 248, "%s size=%zu", __func__, args.size());
std::vector<uint8_t> clipped(args.begin(), args.begin() + LastNonZero(args) + 1);
properties_.SetName(clipped);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_LOCAL_NAME);
+ auto packet = bluetooth::hci::WriteLocalNameCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteExtendedInquiryResponse(packets::PacketView<true> args) {
@@ -918,51 +949,63 @@
// Strip FEC byte and trailing zeros
std::vector<uint8_t> clipped(args.begin() + 1, args.begin() + LastNonZero(args) + 1);
properties_.SetExtendedInquiryData(clipped);
- LOG_WARN("Write EIR Inquiry - Size = %d (%d)", static_cast<int>(properties_.GetExtendedInquiryData().size()),
- static_cast<int>(clipped.size()));
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE);
+ auto packet =
+ bluetooth::hci::WriteExtendedInquiryResponseCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciRefreshEncryptionKey(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
auto args_itr = args.begin();
uint16_t handle = args_itr.extract<uint16_t>();
- SendCommandStatusSuccess(bluetooth::hci::OpCode::REFRESH_ENCRYPTION_KEY);
+ auto status_packet =
+ bluetooth::hci::RefreshEncryptionKeyStatusBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, kNumCommandPackets);
+ send_event_(std::move(status_packet));
// TODO: Support this in the link layer
- auto packet = bluetooth::hci::EncryptionKeyRefreshCompleteBuilder::Create(
- bluetooth::hci::ErrorCode::SUCCESS, handle);
- send_event_(std::move(packet));
+ auto complete_packet =
+ bluetooth::hci::EncryptionKeyRefreshCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, handle);
+ send_event_(std::move(complete_packet));
}
void DualModeController::HciWriteVoiceSetting(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_VOICE_SETTING);
+ auto packet = bluetooth::hci::WriteVoiceSettingCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteCurrentIacLap(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
ASSERT(args.size() == 1 + (3 * args[0])); // count + 3-byte IACs
-
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_CURRENT_IAC_LAP);
+ auto packet = bluetooth::hci::WriteCurrentIacLapCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteInquiryScanActivity(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 4, "%s size=%zu", __func__, args.size());
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::WRITE_INQUIRY_SCAN_ACTIVITY);
+ auto packet = bluetooth::hci::WriteInquiryScanActivityCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciWriteScanEnable(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
link_layer_controller_.SetInquiryScanEnable(args[0] & 0x1);
link_layer_controller_.SetPageScanEnable(args[0] & 0x2);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_SCAN_ENABLE);
+ auto packet = bluetooth::hci::WriteScanEnableCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciSetEventFilter(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::SET_EVENT_FILTER);
+ auto packet = bluetooth::hci::SetEventFilterCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciInquiry(packets::PacketView<true> args) {
@@ -971,13 +1014,17 @@
link_layer_controller_.SetInquiryMaxResponses(args[4]);
link_layer_controller_.StartInquiry(std::chrono::milliseconds(args[3] * 1280));
- SendCommandStatusSuccess(bluetooth::hci::OpCode::INQUIRY);
+ auto packet = bluetooth::hci::InquiryStatusBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciInquiryCancel(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
link_layer_controller_.InquiryCancel();
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::INQUIRY_CANCEL);
+ auto packet = bluetooth::hci::InquiryCancelCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciAcceptConnectionRequest(packets::PacketView<true> args) {
@@ -986,7 +1033,9 @@
bool try_role_switch = args[6] == 0;
auto status =
link_layer_controller_.AcceptConnectionRequest(addr, try_role_switch);
- SendCommandStatus(status, bluetooth::hci::OpCode::ACCEPT_CONNECTION_REQUEST);
+ auto packet = bluetooth::hci::AcceptConnectionRequestStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciRejectConnectionRequest(packets::PacketView<true> args) {
@@ -995,16 +1044,19 @@
Address addr = args_itr.extract<Address>();
uint8_t reason = args_itr.extract<uint8_t>();
auto status = link_layer_controller_.RejectConnectionRequest(addr, reason);
- SendCommandStatus(status, bluetooth::hci::OpCode::REJECT_CONNECTION_REQUEST);
+ auto packet = bluetooth::hci::RejectConnectionRequestStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciLinkKeyRequestReply(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 22, "%s size=%zu", __func__, args.size());
- Address addr = args.begin().extract<Address>();
- packets::PacketView<true> key = args.SubViewLittleEndian(6, 22);
+ auto args_it = args.begin();
+ Address addr = args_it.extract<Address>();
+ auto key = args.begin().extract<std::array<uint8_t, 16>>();
auto status = link_layer_controller_.LinkKeyRequestReply(addr, key);
- auto packet =
- bluetooth::hci::LinkKeyRequestReplyCompleteBuilder::Create(0x01, status);
+ auto packet = bluetooth::hci::LinkKeyRequestReplyCompleteBuilder::Create(
+ kNumCommandPackets, status);
send_event_(std::move(packet));
}
@@ -1014,7 +1066,7 @@
auto status = link_layer_controller_.LinkKeyRequestNegativeReply(addr);
auto packet =
bluetooth::hci::LinkKeyRequestNegativeReplyCompleteBuilder::Create(
- 0x01, status, addr);
+ kNumCommandPackets, status, addr);
send_event_(std::move(packet));
}
@@ -1033,7 +1085,7 @@
}
auto packet = bluetooth::hci::DeleteStoredLinkKeyCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, deleted_keys);
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, deleted_keys);
send_event_(std::move(packet));
}
@@ -1044,9 +1096,11 @@
Address remote_addr = args.begin().extract<Address>();
auto status = link_layer_controller_.SendCommandToRemoteByAddress(
- bluetooth::hci::OpCode::REMOTE_NAME_REQUEST, args, remote_addr, false);
+ bluetooth::hci::OpCode::REMOTE_NAME_REQUEST, args, remote_addr);
- SendCommandStatus(status, bluetooth::hci::OpCode::REMOTE_NAME_REQUEST);
+ auto packet = bluetooth::hci::RemoteNameRequestStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetEventMask(packets::PacketView<true> args) {
@@ -1055,22 +1109,20 @@
uint64_t mask = args.begin().extract<uint64_t>();
link_layer_controller_.SetLeEventMask(mask);
*/
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_EVENT_MASK);
+ auto packet = bluetooth::hci::LeSetEventMaskCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeReadBufferSize(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets2(properties_.GetLeDataPacketLength());
- raw_builder_ptr->AddOctets1(properties_.GetTotalNumLeDataPackets());
+ bluetooth::hci::LeBufferSize le_buffer_size;
+ le_buffer_size.le_data_packet_length_ = properties_.GetLeDataPacketLength();
+ le_buffer_size.total_num_le_packets_ = properties_.GetTotalNumLeDataPackets();
- auto packet = bluetooth::hci::CommandCompleteBuilder::Create(
- 0x01, bluetooth::hci::OpCode::LE_READ_BUFFER_SIZE,
- std::move(raw_builder_ptr));
+ auto packet = bluetooth::hci::LeReadBufferSizeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, le_buffer_size);
send_event_(std::move(packet));
}
@@ -1078,7 +1130,7 @@
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet =
bluetooth::hci::LeReadLocalSupportedFeaturesCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetLeSupportedFeatures());
send_event_(std::move(packet));
}
@@ -1086,7 +1138,9 @@
void DualModeController::HciLeSetRandomAddress(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 6, "%s size=%zu", __func__, args.size());
properties_.SetLeAddress(args.begin().extract<Address>());
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_RANDOM_ADDRESS);
+ auto packet = bluetooth::hci::LeSetRandomAddressCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetAdvertisingParameters(packets::PacketView<true> args) {
@@ -1100,28 +1154,35 @@
args_itr.extract<uint8_t>() /* AdvertisingFilterPolicy */
);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::LE_SET_ADVERTISING_PARAMETERS);
+ auto packet =
+ bluetooth::hci::LeSetAdvertisingParametersCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetAdvertisingData(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 32, "%s size=%zu", __func__, args.size());
properties_.SetLeAdvertisement(std::vector<uint8_t>(args.begin() + 1, args.end()));
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_ADVERTISING_DATA);
+ auto packet = bluetooth::hci::LeSetAdvertisingDataCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetScanResponseData(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 32, "%s size=%zu", __func__, args.size());
properties_.SetLeScanResponse(std::vector<uint8_t>(args.begin() + 1, args.end()));
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_SCAN_RESPONSE_DATA);
+ auto packet = bluetooth::hci::LeSetScanResponseDataCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetAdvertisingEnable(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
auto status = link_layer_controller_.SetLeAdvertisingEnable(
args.begin().extract<uint8_t>());
- SendCommandCompleteOnlyStatus(
- bluetooth::hci::OpCode::LE_SET_ADVERTISING_ENABLE, status);
+ auto packet = bluetooth::hci::LeSetAdvertisingEnableCompleteBuilder::Create(
+ kNumCommandPackets, status);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetScanParameters(packets::PacketView<true> args) {
@@ -1131,15 +1192,18 @@
link_layer_controller_.SetLeScanWindow(args[3] | (args[4], 8));
link_layer_controller_.SetLeAddressType(args[5]);
link_layer_controller_.SetLeScanFilterPolicy(args[6]);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_SCAN_PARAMETERS);
+ auto packet = bluetooth::hci::LeSetScanParametersCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetScanEnable(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 2, "%s size=%zu", __func__, args.size());
- LOG_INFO("SetScanEnable: %d %d", args[0], args[1]);
link_layer_controller_.SetLeScanEnable(args[0]);
link_layer_controller_.SetLeFilterDuplicates(args[1]);
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_SCAN_ENABLE);
+ auto packet = bluetooth::hci::LeSetScanEnableCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeCreateConnection(packets::PacketView<true> args) {
@@ -1166,18 +1230,23 @@
auto status = link_layer_controller_.SetLeConnect(true);
- SendCommandStatus(status, bluetooth::hci::OpCode::LE_CREATE_CONNECTION);
+ auto packet = bluetooth::hci::LeCreateConnectionStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeConnectionUpdate(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 14, "%s size=%zu", __func__, args.size());
- SendCommandStatus(
+ auto status_packet = bluetooth::hci::LeConnectionUpdateStatusBuilder::Create(
bluetooth::hci::ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR,
- bluetooth::hci::OpCode::LE_CONNECTION_UPDATE);
+ kNumCommandPackets);
+ send_event_(std::move(status_packet));
- auto packet = bluetooth::hci::LeConnectionUpdateCompleteBuilder::Create(
- bluetooth::hci::ErrorCode::SUCCESS, 0x0002, 0x0006, 0x0000, 0x01f4);
+ auto complete_packet =
+ bluetooth::hci::LeConnectionUpdateCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, 0x0002, 0x0006, 0x0000, 0x01f4);
+ send_event_(std::move(complete_packet));
}
void DualModeController::HciCreateConnection(packets::PacketView<true> args) {
@@ -1193,7 +1262,9 @@
auto status = link_layer_controller_.CreateConnection(
address, packet_type, page_scan_mode, clock_offset, allow_role_switch);
- SendCommandStatus(status, bluetooth::hci::OpCode::CREATE_CONNECTION);
+ auto packet = bluetooth::hci::CreateConnectionStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciDisconnect(packets::PacketView<true> args) {
@@ -1205,13 +1276,17 @@
auto status = link_layer_controller_.Disconnect(handle, reason);
- SendCommandStatus(status, bluetooth::hci::OpCode::DISCONNECT);
+ auto packet = bluetooth::hci::DisconnectStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeConnectionCancel(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
link_layer_controller_.SetLeConnect(false);
- SendCommandStatusSuccess(bluetooth::hci::OpCode::LE_CREATE_CONNECTION_CANCEL);
+ auto packet = bluetooth::hci::LeCreateConnectionCancelStatusBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, kNumCommandPackets);
+ send_event_(std::move(packet));
/* For testing Jakub's patch: Figure out a neat way to call this without
recompiling. I'm thinking about a bad device. */
/*
@@ -1223,7 +1298,7 @@
void DualModeController::HciLeReadWhiteListSize(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::LeReadWhiteListSizeCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetLeWhiteListSize());
send_event_(std::move(packet));
}
@@ -1231,24 +1306,28 @@
void DualModeController::HciLeClearWhiteList(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
link_layer_controller_.LeWhiteListClear();
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_CLEAR_WHITE_LIST);
+ auto packet = bluetooth::hci::LeClearWhiteListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeAddDeviceToWhiteList(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 7, "%s size=%zu", __func__, args.size());
if (link_layer_controller_.LeWhiteListFull()) {
- SendCommandCompleteOnlyStatus(
- bluetooth::hci::OpCode::LE_ADD_DEVICE_TO_WHITE_LIST,
+ auto packet = bluetooth::hci::LeAddDeviceToWhiteListCompleteBuilder::Create(
+ kNumCommandPackets,
bluetooth::hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED);
+ send_event_(std::move(packet));
return;
}
auto args_itr = args.begin();
uint8_t addr_type = args_itr.extract<uint8_t>();
Address address = args_itr.extract<Address>();
link_layer_controller_.LeWhiteListAddDevice(address, addr_type);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::LE_ADD_DEVICE_TO_WHITE_LIST);
+ auto packet = bluetooth::hci::LeAddDeviceToWhiteListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeRemoveDeviceFromWhiteList(packets::PacketView<true> args) {
@@ -1258,15 +1337,19 @@
uint8_t addr_type = args_itr.extract<uint8_t>();
Address address = args_itr.extract<Address>();
link_layer_controller_.LeWhiteListRemoveDevice(address, addr_type);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST);
+ auto packet =
+ bluetooth::hci::LeRemoveDeviceFromWhiteListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeClearResolvingList(
packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
link_layer_controller_.LeResolvingListClear();
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_CLEAR_RESOLVING_LIST);
+ auto packet = bluetooth::hci::LeClearResolvingListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeAddDeviceToResolvingList(
@@ -1274,9 +1357,11 @@
ASSERT_LOG(args.size() == 39, "%s size=%zu", __func__, args.size());
if (link_layer_controller_.LeResolvingListFull()) {
- SendCommandCompleteOnlyStatus(
- bluetooth::hci::OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST,
- bluetooth::hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED);
+ auto packet =
+ bluetooth::hci::LeAddDeviceToResolvingListCompleteBuilder::Create(
+ kNumCommandPackets,
+ bluetooth::hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED);
+ send_event_(std::move(packet));
return;
}
auto args_itr = args.begin();
@@ -1296,8 +1381,10 @@
link_layer_controller_.LeResolvingListAddDevice(address, addr_type, peerIrk,
localIrk);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST);
+ auto packet =
+ bluetooth::hci::LeAddDeviceToResolvingListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeRemoveDeviceFromResolvingList(
@@ -1308,8 +1395,10 @@
uint8_t addr_type = args_itr.extract<uint8_t>();
Address address = args_itr.extract<Address>();
link_layer_controller_.LeResolvingListRemoveDevice(address, addr_type);
- SendCommandCompleteSuccess(
- bluetooth::hci::OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST);
+ auto packet =
+ bluetooth::hci::LeRemoveDeviceFromResolvingListCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeSetPrivacyMode(packets::PacketView<true> args) {
@@ -1326,7 +1415,9 @@
peer_identity_address_type, peer_identity_address, privacy_mode);
}
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::LE_SET_PRIVACY_MODE);
+ auto packet = bluetooth::hci::LeSetPrivacyModeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeReadRemoteFeatures(packets::PacketView<true> args) {
@@ -1337,7 +1428,9 @@
auto status = link_layer_controller_.SendCommandToRemoteByHandle(
bluetooth::hci::OpCode::LE_READ_REMOTE_FEATURES, args, handle);
- SendCommandStatus(status, bluetooth::hci::OpCode::LE_READ_REMOTE_FEATURES);
+ auto packet = bluetooth::hci::LeConnectionUpdateStatusBuilder::Create(
+ status, kNumCommandPackets);
+ send_event_(std::move(packet));
}
void DualModeController::HciLeRand(packets::PacketView<true> args) {
@@ -1348,14 +1441,14 @@
}
auto packet = bluetooth::hci::LeRandCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS, random_val);
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS, random_val);
send_event_(std::move(packet));
}
void DualModeController::HciLeReadSupportedStates(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::LeReadSupportedStatesCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
properties_.GetLeSupportedStates());
send_event_(std::move(packet));
}
@@ -1364,9 +1457,8 @@
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
vector<uint8_t> caps = properties_.GetLeVendorCap();
if (caps.size() == 0) {
- SendCommandCompleteOnlyStatus(
- bluetooth::hci::OpCode::LE_GET_VENDOR_CAPABILITIES,
- bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+ SendCommandCompleteUnknownOpCodeEvent(static_cast<uint16_t>(
+ bluetooth::hci::OpCode::LE_GET_VENDOR_CAPABILITIES));
return;
}
@@ -1377,33 +1469,33 @@
raw_builder_ptr->AddOctets(properties_.GetLeVendorCap());
auto packet = bluetooth::hci::CommandCompleteBuilder::Create(
- 0x01, bluetooth::hci::OpCode::LE_GET_VENDOR_CAPABILITIES,
+ kNumCommandPackets, bluetooth::hci::OpCode::LE_GET_VENDOR_CAPABILITIES,
std::move(raw_builder_ptr));
send_event_(std::move(packet));
}
void DualModeController::HciLeVendorMultiAdv(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
- SendCommandCompleteOnlyStatus(bluetooth::hci::OpCode::LE_MULTI_ADVT,
- bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+ SendCommandCompleteUnknownOpCodeEvent(
+ static_cast<uint16_t>(bluetooth::hci::OpCode::LE_MULTI_ADVT));
}
void DualModeController::HciLeAdvertisingFilter(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
- SendCommandCompleteOnlyStatus(bluetooth::hci::OpCode::LE_ADV_FILTER,
- bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+ SendCommandCompleteUnknownOpCodeEvent(
+ static_cast<uint16_t>(bluetooth::hci::OpCode::LE_ADV_FILTER));
}
void DualModeController::HciLeEnergyInfo(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
- SendCommandCompleteOnlyStatus(bluetooth::hci::OpCode::LE_ENERGY_INFO,
- bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+ SendCommandCompleteUnknownOpCodeEvent(
+ static_cast<uint16_t>(bluetooth::hci::OpCode::LE_ENERGY_INFO));
}
void DualModeController::HciLeExtendedScanParams(packets::PacketView<true> args) {
ASSERT(args.size() > 0);
- SendCommandCompleteOnlyStatus(bluetooth::hci::OpCode::LE_EXTENDED_SCAN_PARAMS,
- bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+ SendCommandCompleteUnknownOpCodeEvent(
+ static_cast<uint16_t>(bluetooth::hci::OpCode::LE_EXTENDED_SCAN_PARAMS));
}
void DualModeController::HciLeStartEncryption(packets::PacketView<true> args) {
@@ -1417,13 +1509,14 @@
// for (size_t i = 0; i < 16; i++) {
// long_term_key.push_back(args_itr.extract<uint18_t>();
// }
- SendCommandStatus(bluetooth::hci::ErrorCode::SUCCESS,
- bluetooth::hci::OpCode::LE_START_ENCRYPTION);
+ auto status_packet = bluetooth::hci::LeStartEncryptionStatusBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, kNumCommandPackets);
+ send_event_(std::move(status_packet));
- auto packet = bluetooth::hci::EncryptionChangeBuilder::Create(
+ auto complete_packet = bluetooth::hci::EncryptionChangeBuilder::Create(
bluetooth::hci::ErrorCode::SUCCESS, handle,
bluetooth::hci::EncryptionEnabled::OFF);
- send_event_(std::move(packet));
+ send_event_(std::move(complete_packet));
#if 0
std::shared_ptr<packets::AclPacketBuilder> encryption_information =
@@ -1481,7 +1574,7 @@
void DualModeController::HciReadLoopbackMode(packets::PacketView<true> args) {
ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
auto packet = bluetooth::hci::ReadLoopbackModeCompleteBuilder::Create(
- 0x01, bluetooth::hci::ErrorCode::SUCCESS,
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS,
static_cast<bluetooth::hci::LoopbackMode>(loopback_mode_));
send_event_(std::move(packet));
}
@@ -1501,7 +1594,9 @@
bluetooth::hci::ErrorCode::SUCCESS, sco_handle, properties_.GetAddress(),
bluetooth::hci::LinkType::SCO, bluetooth::hci::Enable::DISABLED);
send_event_(std::move(packet_sco));
- SendCommandCompleteSuccess(bluetooth::hci::OpCode::WRITE_LOOPBACK_MODE);
+ auto packet = bluetooth::hci::WriteLoopbackModeCompleteBuilder::Create(
+ kNumCommandPackets, bluetooth::hci::ErrorCode::SUCCESS);
+ send_event_(std::move(packet));
}
void DualModeController::SetAddress(Address address) {
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
index d18f7e4..bd9c17d 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
@@ -286,7 +286,7 @@
void HciWriteLeHostSupport(packets::PacketView<true> args);
// 7.3.92
- void HciWriteSecureConnectionHostSupport(packets::PacketView<true> args);
+ void HciWriteSecureConnectionsHostSupport(packets::PacketView<true> args);
// Informational Parameters Commands
// Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4
@@ -432,24 +432,11 @@
// Creates a command complete event and sends it back to the HCI.
void SendCommandComplete(hci::OpCode command_opcode, const std::vector<uint8_t>& return_parameters) const;
- // Sends a command complete event with no return parameters.
- void SendCommandCompleteSuccess(bluetooth::hci::OpCode command_opcode) const;
-
void SendCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode) const;
- // Sends a command complete event with no return parameters.
- void SendCommandCompleteOnlyStatus(bluetooth::hci::OpCode command_opcode,
- bluetooth::hci::ErrorCode status) const;
-
- // Creates a command status event and sends it back to the HCI.
- void SendCommandStatus(bluetooth::hci::ErrorCode status,
- bluetooth::hci::OpCode command_opcode) const;
-
- // Sends a command status event with default event parameters.
- void SendCommandStatusSuccess(bluetooth::hci::OpCode command_opcode) const;
-
// Callbacks to send packets back to the HCI.
- std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_acl_;
+ std::function<void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>
+ send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>
send_event_;
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index a272f84..aebe621 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -19,9 +19,7 @@
#include "hci.h"
#include "include/le_advertisement.h"
#include "os/log.h"
-#include "packets/hci/acl_packet_builder.h"
#include "packets/hci/command_packet_view.h"
-#include "packets/hci/sco_packet_builder.h"
#include "packets/raw_builder.h"
#include "packet/raw_builder.h"
@@ -32,6 +30,8 @@
namespace test_vendor_lib {
+constexpr uint16_t kNumCommandPackets = 0x01;
+
// TODO: Model Rssi?
static uint8_t GetRssi() {
static uint8_t rssi = 0;
@@ -61,39 +61,60 @@
}
bluetooth::hci::ErrorCode LinkLayerController::SendCommandToRemoteByAddress(
- bluetooth::hci::OpCode opcode, PacketView<true> args, const Address& remote,
- bool use_public_address) {
- Address local_address;
- if (use_public_address) {
- local_address = properties_.GetAddress();
- } else {
- local_address = properties_.GetLeAddress();
+ bluetooth::hci::OpCode opcode, PacketView<true> args,
+ const Address& remote) {
+ Address local_address = properties_.GetAddress();
+
+ switch (opcode) {
+ case (bluetooth::hci::OpCode::REMOTE_NAME_REQUEST):
+ // LMP features get requested with remote name requests.
+ SendLinkLayerPacket(model::packets::ReadRemoteLmpFeaturesBuilder::Create(
+ local_address, remote));
+ SendLinkLayerPacket(model::packets::RemoteNameRequestBuilder::Create(
+ local_address, remote));
+ break;
+ case (bluetooth::hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES):
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteSupportedFeaturesBuilder::Create(
+ local_address, remote));
+ break;
+ case (bluetooth::hci::OpCode::READ_REMOTE_EXTENDED_FEATURES): {
+ uint8_t page_number =
+ (args.begin() + 2).extract<uint8_t>(); // skip the handle
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteExtendedFeaturesBuilder::Create(
+ local_address, remote, page_number));
+ } break;
+ case (bluetooth::hci::OpCode::READ_REMOTE_VERSION_INFORMATION):
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteVersionInformationBuilder::Create(
+ local_address, remote));
+ break;
+ case (bluetooth::hci::OpCode::READ_CLOCK_OFFSET):
+ SendLinkLayerPacket(model::packets::ReadClockOffsetBuilder::Create(
+ local_address, remote));
+ break;
+ default:
+ LOG_INFO("Dropping unhandled command 0x%04x",
+ static_cast<uint16_t>(opcode));
+ return bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND;
}
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- std::vector<uint8_t> payload_bytes(args.begin(), args.end());
- raw_builder_ptr->AddOctets2(static_cast<uint16_t>(opcode));
- raw_builder_ptr->AddOctets(payload_bytes);
-
- auto command = model::packets::CommandBuilder::Create(
- local_address, remote, std::move(raw_builder_ptr));
-
- SendLinkLayerPacket(std::move(command));
return bluetooth::hci::ErrorCode::SUCCESS;
}
bluetooth::hci::ErrorCode LinkLayerController::SendCommandToRemoteByHandle(
bluetooth::hci::OpCode opcode, PacketView<true> args, uint16_t handle) {
// TODO: Handle LE connections
- bool use_public_address = true;
if (!connections_.HasHandle(handle)) {
return bluetooth::hci::ErrorCode::UNKNOWN_CONNECTION;
}
- return SendCommandToRemoteByAddress(opcode, args, connections_.GetAddress(handle), use_public_address);
+ return SendCommandToRemoteByAddress(opcode, args,
+ connections_.GetAddress(handle));
}
-hci::Status LinkLayerController::SendAclToRemote(AclPacketView acl_packet) {
+hci::Status LinkLayerController::SendAclToRemote(
+ bluetooth::hci::AclPacketView acl_packet) {
uint16_t handle = acl_packet.GetHandle();
if (!connections_.HasHandle(handle)) {
return hci::Status::UNKNOWN_CONNECTION;
@@ -109,15 +130,13 @@
static_cast<int>(acl_packet.size()));
ScheduleTask(milliseconds(5), [this, handle]() {
- std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
- std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(0x01);
- raw_builder_ptr->AddOctets2(handle);
- raw_builder_ptr->AddOctets2(0x01);
-
- auto packet = bluetooth::hci::EventPacketBuilder::Create(
- bluetooth::hci::EventCode::NUMBER_OF_COMPLETED_PACKETS,
- std::move(raw_builder_ptr));
+ std::vector<bluetooth::hci::CompletedPackets> completed_packets;
+ bluetooth::hci::CompletedPackets cp;
+ cp.connection_handle_ = handle;
+ cp.host_num_of_completed_packets_ = kNumCommandPackets;
+ completed_packets.push_back(cp);
+ auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
+ completed_packets);
send_event_(std::move(packet));
});
@@ -129,8 +148,8 @@
uint16_t first_two_bytes =
static_cast<uint16_t>(acl_packet.GetHandle()) +
- (static_cast<uint16_t>(acl_packet.GetPacketBoundaryFlags()) << 12) +
- (static_cast<uint16_t>(acl_packet.GetBroadcastFlags()) << 14);
+ (static_cast<uint16_t>(acl_packet.GetPacketBoundaryFlag()) << 12) +
+ (static_cast<uint16_t>(acl_packet.GetBroadcastFlag()) << 14);
raw_builder_ptr->AddOctets2(first_two_bytes);
raw_builder_ptr->AddOctets2(static_cast<uint16_t>(payload_bytes.size()));
raw_builder_ptr->AddOctets(payload_bytes);
@@ -158,9 +177,6 @@
case model::packets::PacketType::ACL:
IncomingAclPacket(incoming);
break;
- case model::packets::PacketType::COMMAND:
- IncomingCommandPacket(incoming);
- break;
case model::packets::PacketType::DISCONNECT:
IncomingDisconnectPacket(incoming);
break;
@@ -181,6 +197,9 @@
case model::packets::PacketType::IO_CAPABILITY_REQUEST:
IncomingIoCapabilityRequestPacket(incoming);
break;
+ case model::packets::PacketType::IO_CAPABILITY_RESPONSE:
+ IncomingIoCapabilityResponsePacket(incoming);
+ break;
case model::packets::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE:
IncomingIoCapabilityNegativeResponsePacket(incoming);
break;
@@ -215,11 +234,45 @@
case model::packets::PacketType::PAGE_REJECT:
IncomingPageRejectPacket(incoming);
break;
- case model::packets::PacketType::RESPONSE:
- IncomingResponsePacket(incoming);
+ case (model::packets::PacketType::REMOTE_NAME_REQUEST):
+ IncomingRemoteNameRequest(incoming);
+ break;
+ case (model::packets::PacketType::REMOTE_NAME_REQUEST_RESPONSE):
+ IncomingRemoteNameRequestResponse(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_SUPPORTED_FEATURES):
+ IncomingReadRemoteSupportedFeatures(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_SUPPORTED_FEATURES_RESPONSE):
+ IncomingReadRemoteSupportedFeaturesResponse(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_LMP_FEATURES):
+ IncomingReadRemoteLmpFeatures(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_LMP_FEATURES_RESPONSE):
+ IncomingReadRemoteLmpFeaturesResponse(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_EXTENDED_FEATURES):
+ IncomingReadRemoteExtendedFeatures(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_EXTENDED_FEATURES_RESPONSE):
+ IncomingReadRemoteExtendedFeaturesResponse(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_VERSION_INFORMATION):
+ IncomingReadRemoteVersion(incoming);
+ break;
+ case (model::packets::PacketType::READ_REMOTE_VERSION_INFORMATION_RESPONSE):
+ IncomingReadRemoteVersionResponse(incoming);
+ break;
+ case (model::packets::PacketType::READ_CLOCK_OFFSET):
+ IncomingReadClockOffset(incoming);
+ break;
+ case (model::packets::PacketType::READ_CLOCK_OFFSET_RESPONSE):
+ IncomingReadClockOffsetResponse(incoming);
break;
default:
- LOG_WARN("Dropping unhandled packet of type %d", static_cast<int32_t>(incoming.GetType()));
+ LOG_WARN("Dropping unhandled packet of type %s",
+ model::packets::PacketTypeText(incoming.GetType()).c_str());
}
}
@@ -234,95 +287,171 @@
std::shared_ptr<std::vector<uint8_t>> payload_bytes =
std::make_shared<std::vector<uint8_t>>(payload.begin(), payload.end());
- AclPacketView acl_view = AclPacketView::Create(payload_bytes);
+ bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian> raw_packet(
+ payload_bytes);
+ auto acl_view = bluetooth::hci::AclPacketView::Create(raw_packet);
+ ASSERT(acl_view.IsValid());
+
LOG_INFO("%s: remote handle 0x%x size %d", __func__, acl_view.GetHandle(), static_cast<int>(acl_view.size()));
uint16_t local_handle = connections_.GetHandle(incoming.GetSourceAddress());
LOG_INFO("%s: local handle 0x%x", __func__, local_handle);
- acl::PacketBoundaryFlagsType boundary_flags = acl_view.GetPacketBoundaryFlags();
- acl::BroadcastFlagsType broadcast_flags = acl_view.GetBroadcastFlags();
- std::unique_ptr<RawBuilder> builder = std::make_unique<RawBuilder>();
- std::vector<uint8_t> raw_data(acl_view.GetPayload().begin(),
- acl_view.GetPayload().end());
- builder->AddOctets(raw_data);
- send_acl_(AclPacketBuilder::Create(local_handle, boundary_flags, broadcast_flags, std::move(builder))->ToVector());
-}
-
-void LinkLayerController::IncomingCommandPacket(
- model::packets::LinkLayerPacketView incoming) {
- // TODO: Check the destination address to see if this packet is for me.
- auto command = model::packets::CommandView::Create(incoming);
- ASSERT(command.IsValid());
-
- auto args = command.GetPayload().begin();
- std::vector<uint64_t> response_data;
- hci::OpCode opcode = static_cast<hci::OpCode>(args.extract<uint16_t>());
std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
std::make_unique<bluetooth::packet::RawBuilder>();
+ std::vector<uint8_t> payload_data(acl_view.GetPayload().begin(),
+ acl_view.GetPayload().end());
+ raw_builder_ptr->AddOctets(payload_data);
- switch (opcode) {
- case (hci::OpCode::REMOTE_NAME_REQUEST): {
- std::vector<uint8_t> name = properties_.GetName();
- LOG_INFO("Remote Name (Local Name) %d", static_cast<int>(name.size()));
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets8(name.size());
- raw_builder_ptr->AddOctets(name);
- } break;
- case (hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES):
- LOG_INFO("(%s) Remote Supported Features Requested by: %s %x",
- incoming.GetDestinationAddress().ToString().c_str(), incoming.GetSourceAddress().ToString().c_str(),
- static_cast<int>(properties_.GetSupportedFeatures()));
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets8(properties_.GetSupportedFeatures());
- break;
- case (hci::OpCode::READ_REMOTE_EXTENDED_FEATURES): {
- uint8_t page_number = (args + 2).extract<uint8_t>(); // skip the handle
- LOG_INFO("(%s) Remote Extended Features %d Requested by: %s", incoming.GetDestinationAddress().ToString().c_str(),
- page_number, incoming.GetSourceAddress().ToString().c_str());
- uint8_t max_page_number = properties_.GetExtendedFeaturesMaximumPageNumber();
- if (page_number > max_page_number) {
- raw_builder_ptr->AddOctets1(static_cast<uint8_t>(
- bluetooth::hci::ErrorCode::INVALID_HCI_COMMAND_PARAMETERS));
- raw_builder_ptr->AddOctets1(page_number);
- raw_builder_ptr->AddOctets1(max_page_number);
- raw_builder_ptr->AddOctets8(0);
- } else {
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets1(page_number);
- raw_builder_ptr->AddOctets1(max_page_number);
- raw_builder_ptr->AddOctets8(
- properties_.GetExtendedFeatures(page_number));
- }
- } break;
- case (hci::OpCode::READ_REMOTE_VERSION_INFORMATION):
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets1(properties_.GetLmpPalVersion());
- raw_builder_ptr->AddOctets2(properties_.GetManufacturerName());
- raw_builder_ptr->AddOctets2(properties_.GetLmpPalSubversion());
- break;
- case (hci::OpCode::READ_CLOCK_OFFSET):
- raw_builder_ptr->AddOctets1(
- static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS));
- raw_builder_ptr->AddOctets2(properties_.GetClockOffset());
- break;
- default:
- LOG_INFO("Dropping unhandled command 0x%04x", static_cast<uint16_t>(opcode));
- return;
+ auto acl_packet = bluetooth::hci::AclPacketBuilder::Create(
+ local_handle, acl_view.GetPacketBoundaryFlag(),
+ acl_view.GetBroadcastFlag(), std::move(raw_builder_ptr));
+
+ send_acl_(std::move(acl_packet));
+}
+
+void LinkLayerController::IncomingRemoteNameRequest(
+ model::packets::LinkLayerPacketView packet) {
+ auto view = model::packets::RemoteNameRequestView::Create(packet);
+ ASSERT(view.IsValid());
+
+ SendLinkLayerPacket(model::packets::RemoteNameRequestResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(),
+ properties_.GetName()));
+}
+
+void LinkLayerController::IncomingRemoteNameRequestResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view = model::packets::RemoteNameRequestResponseView::Create(packet);
+ ASSERT(view.IsValid());
+
+ send_event_(bluetooth::hci::RemoteNameRequestCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, packet.GetSourceAddress(),
+ view.GetName()));
+}
+
+void LinkLayerController::IncomingReadRemoteLmpFeatures(
+ model::packets::LinkLayerPacketView packet) {
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteLmpFeaturesResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(),
+ properties_.GetExtendedFeatures(1)));
+}
+
+void LinkLayerController::IncomingReadRemoteLmpFeaturesResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view = model::packets::ReadRemoteLmpFeaturesResponseView::Create(packet);
+ ASSERT(view.IsValid());
+ send_event_(
+ bluetooth::hci::RemoteHostSupportedFeaturesNotificationBuilder::Create(
+ packet.GetSourceAddress(), view.GetFeatures()));
+}
+
+void LinkLayerController::IncomingReadRemoteSupportedFeatures(
+ model::packets::LinkLayerPacketView packet) {
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteSupportedFeaturesResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(),
+ properties_.GetSupportedFeatures()));
+}
+
+void LinkLayerController::IncomingReadRemoteSupportedFeaturesResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view =
+ model::packets::ReadRemoteSupportedFeaturesResponseView::Create(packet);
+ ASSERT(view.IsValid());
+ Address source = packet.GetSourceAddress();
+ if (connections_.IsDeviceConnected(source)) {
+ uint16_t handle = connections_.GetHandle(source);
+ send_event_(
+ bluetooth::hci::ReadRemoteSupportedFeaturesCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, handle, view.GetFeatures()));
+ } else {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
}
+}
- for (uint64_t data : response_data) {
- raw_builder_ptr->AddOctets8(data);
+void LinkLayerController::IncomingReadRemoteExtendedFeatures(
+ model::packets::LinkLayerPacketView packet) {
+ auto view = model::packets::ReadRemoteExtendedFeaturesView::Create(packet);
+ ASSERT(view.IsValid());
+ uint8_t page_number = view.GetPageNumber();
+ uint8_t error_code = static_cast<uint8_t>(bluetooth::hci::ErrorCode::SUCCESS);
+ if (page_number > properties_.GetExtendedFeaturesMaximumPageNumber()) {
+ error_code = static_cast<uint8_t>(
+ bluetooth::hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS);
}
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteExtendedFeaturesResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(), error_code,
+ page_number, properties_.GetExtendedFeaturesMaximumPageNumber(),
+ properties_.GetExtendedFeatures(view.GetPageNumber())));
+}
- auto response = model::packets::ResponseBuilder::Create(
- properties_.GetAddress(), incoming.GetSourceAddress(),
- static_cast<uint16_t>(opcode), std::move(raw_builder_ptr));
+void LinkLayerController::IncomingReadRemoteExtendedFeaturesResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view =
+ model::packets::ReadRemoteExtendedFeaturesResponseView::Create(packet);
+ ASSERT(view.IsValid());
+ Address source = packet.GetSourceAddress();
+ if (connections_.IsDeviceConnected(source)) {
+ uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+ send_event_(
+ bluetooth::hci::ReadRemoteExtendedFeaturesCompleteBuilder::Create(
+ static_cast<bluetooth::hci::ErrorCode>(view.GetStatus()), handle,
+ view.GetPageNumber(), view.GetMaxPageNumber(), view.GetFeatures()));
+ } else {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
+ }
+}
- SendLinkLayerPacket(std::move(response));
+void LinkLayerController::IncomingReadRemoteVersion(
+ model::packets::LinkLayerPacketView packet) {
+ SendLinkLayerPacket(
+ model::packets::ReadRemoteSupportedFeaturesResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(),
+ properties_.GetSupportedFeatures()));
+}
+
+void LinkLayerController::IncomingReadRemoteVersionResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view =
+ model::packets::ReadRemoteVersionInformationResponseView::Create(packet);
+ ASSERT(view.IsValid());
+ Address source = packet.GetSourceAddress();
+ if (connections_.IsDeviceConnected(source)) {
+ uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+ send_event_(
+ bluetooth::hci::ReadRemoteVersionInformationCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, handle, view.GetLmpVersion(),
+ view.GetManufacturerName(), view.GetLmpSubversion()));
+ } else {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
+ }
+}
+
+void LinkLayerController::IncomingReadClockOffset(
+ model::packets::LinkLayerPacketView packet) {
+ SendLinkLayerPacket(model::packets::ReadClockOffsetResponseBuilder::Create(
+ packet.GetDestinationAddress(), packet.GetSourceAddress(),
+ properties_.GetClockOffset()));
+}
+
+void LinkLayerController::IncomingReadClockOffsetResponse(
+ model::packets::LinkLayerPacketView packet) {
+ auto view = model::packets::ReadClockOffsetResponseView::Create(packet);
+ ASSERT(view.IsValid());
+ Address source = packet.GetSourceAddress();
+ if (connections_.IsDeviceConnected(source)) {
+ uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+ send_event_(bluetooth::hci::ReadClockOffsetCompleteBuilder::Create(
+ bluetooth::hci::ErrorCode::SUCCESS, handle, view.GetOffset()));
+ } else {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
+ }
}
void LinkLayerController::IncomingDisconnectPacket(
@@ -354,12 +483,19 @@
LOG_INFO("%s: Unknown connection @%s", __func__, peer.ToString().c_str());
return;
}
- auto packet = bluetooth::hci::EncryptionChangeBuilder::Create(
+ send_event_(bluetooth::hci::EncryptionChangeBuilder::Create(
bluetooth::hci::ErrorCode::SUCCESS, handle,
- bluetooth::hci::EncryptionEnabled::ON);
- send_event_(std::move(packet));
+ bluetooth::hci::EncryptionEnabled::ON));
+
+ uint16_t count = security_manager_.ReadKey(peer);
+ if (count == 0) {
+ LOG_ERROR("NO KEY HERE for %s", peer.ToString().c_str());
+ return;
+ }
+ auto array = security_manager_.GetKey(peer);
+ std::vector<uint8_t> key_vec{array.begin(), array.end()};
auto response = model::packets::EncryptConnectionResponseBuilder::Create(
- properties_.GetAddress(), peer, security_manager_.GetKey(peer));
+ properties_.GetAddress(), peer, key_vec);
SendLinkLayerPacket(std::move(response));
}
@@ -428,7 +564,6 @@
switch (basic_inquiry_response.GetInquiryType()) {
case (model::packets::InquiryType::STANDARD): {
- LOG_WARN("Incoming Standard Inquiry Response");
// TODO: Support multiple inquiries in the same packet.
auto inquiry_response =
model::packets::InquiryResponseView::Create(basic_inquiry_response);
@@ -447,7 +582,6 @@
} break;
case (model::packets::InquiryType::RSSI): {
- LOG_WARN("Incoming RSSI Inquiry Response");
auto inquiry_response =
model::packets::InquiryResponseWithRssiView::Create(
basic_inquiry_response);
@@ -465,7 +599,6 @@
} break;
case (model::packets::InquiryType::EXTENDED): {
- LOG_WARN("Incoming Extended Inquiry Response");
auto inquiry_response =
model::packets::ExtendedInquiryResponseView::Create(
basic_inquiry_response);
@@ -473,7 +606,7 @@
std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
std::make_unique<bluetooth::packet::RawBuilder>();
- raw_builder_ptr->AddOctets1(0x01); // num_responses
+ raw_builder_ptr->AddOctets1(kNumCommandPackets);
raw_builder_ptr->AddAddress(inquiry_response.GetSourceAddress());
raw_builder_ptr->AddOctets1(inquiry_response.GetPageScanRepetitionMode());
raw_builder_ptr->AddOctets1(0x00); // _reserved_
@@ -735,7 +868,8 @@
ASSERT(page.IsValid());
LOG_INFO("%s from %s", __func__, incoming.GetSourceAddress().ToString().c_str());
- if (!connections_.CreatePendingConnection(incoming.GetSourceAddress())) {
+ if (!connections_.CreatePendingConnection(
+ incoming.GetSourceAddress(), properties_.GetAuthenticationEnable())) {
// Send a response to indicate that we're busy, or drop the packet?
LOG_WARN("%s: Failed to create a pending connection for %s", __func__,
incoming.GetSourceAddress().ToString().c_str());
@@ -767,8 +901,10 @@
void LinkLayerController::IncomingPageResponsePacket(
model::packets::LinkLayerPacketView incoming) {
- LOG_INFO("%s: %s", __func__, incoming.GetSourceAddress().ToString().c_str());
- uint16_t handle = connections_.CreateConnection(incoming.GetSourceAddress());
+ Address peer = incoming.GetSourceAddress();
+ LOG_INFO("%s: %s", __func__, peer.ToString().c_str());
+ bool awaiting_authentication = connections_.AuthenticatePendingConnection();
+ uint16_t handle = connections_.CreateConnection(peer);
if (handle == acl::kReservedHandle) {
LOG_WARN("%s: No free handles", __func__);
return;
@@ -777,71 +913,11 @@
bluetooth::hci::ErrorCode::SUCCESS, handle, incoming.GetSourceAddress(),
bluetooth::hci::LinkType::ACL, bluetooth::hci::Enable::DISABLED);
send_event_(std::move(packet));
-}
-void LinkLayerController::IncomingResponsePacket(
- model::packets::LinkLayerPacketView incoming) {
- auto response = model::packets::ResponseView::Create(incoming);
- ASSERT(response.IsValid());
-
- // TODO: Check to see if I'm expecting this response.
-
- hci::OpCode opcode = static_cast<hci::OpCode>(response.GetOpcode());
- auto args = response.GetPayload().begin();
- auto status = static_cast<bluetooth::hci::ErrorCode>(args.extract<uint8_t>());
-
- uint16_t handle = connections_.GetHandle(incoming.GetSourceAddress());
-
- switch (opcode) {
- case (hci::OpCode::REMOTE_NAME_REQUEST): {
- std::array<uint8_t, 248> remote_name;
- remote_name.fill(0x00);
- uint64_t len = args.extract<uint64_t>();
- if (len > 247) {
- len = 247; // one byte for NULL octet (0x00)
- }
- for (uint64_t i = 0; i < len; i++) {
- remote_name[i] = args.extract<uint8_t>();
- }
- auto packet = bluetooth::hci::RemoteNameRequestCompleteBuilder::Create(
- status, incoming.GetSourceAddress(), remote_name);
- send_event_(std::move(packet));
- } break;
- case (hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES): {
- auto packet =
- bluetooth::hci::ReadRemoteSupportedFeaturesCompleteBuilder::Create(
- status, handle, args.extract<uint64_t>());
- send_event_(std::move(packet));
- } break;
- case (hci::OpCode::READ_REMOTE_EXTENDED_FEATURES): {
- if (status == bluetooth::hci::ErrorCode::SUCCESS) {
- auto packet =
- bluetooth::hci::ReadRemoteExtendedFeaturesCompleteBuilder::Create(
- status, handle, args.extract<uint8_t>(),
- args.extract<uint8_t>(), args.extract<uint64_t>());
- send_event_(std::move(packet));
- } else {
- auto packet =
- bluetooth::hci::ReadRemoteExtendedFeaturesCompleteBuilder::Create(
- status, handle, 0, 0, 0);
- send_event_(std::move(packet));
- }
- } break;
- case (hci::OpCode::READ_REMOTE_VERSION_INFORMATION): {
- auto packet =
- bluetooth::hci::ReadRemoteVersionInformationCompleteBuilder::Create(
- status, handle, args.extract<uint8_t>(), args.extract<uint16_t>(),
- args.extract<uint16_t>());
- send_event_(std::move(packet));
- LOG_INFO("Read remote version handle 0x%04x", handle);
- } break;
- case (hci::OpCode::READ_CLOCK_OFFSET): {
- auto packet = bluetooth::hci::ReadClockOffsetCompleteBuilder::Create(
- status, handle, args.extract<uint16_t>());
- send_event_(std::move(packet));
- } break;
- default:
- LOG_INFO("Unhandled response to command 0x%04x", static_cast<uint16_t>(opcode));
+ if (awaiting_authentication) {
+ ScheduleTask(milliseconds(5), [this, peer, handle]() {
+ HandleAuthenticationRequest(peer, handle);
+ });
}
}
@@ -889,7 +965,8 @@
}
void LinkLayerController::RegisterAclChannel(
- const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+ const std::function<
+ void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>& callback) {
send_acl_ = callback;
}
@@ -964,25 +1041,24 @@
ASSERT(security_manager_.GetAuthenticationAddress() == peer);
// TODO: Public key exchange first?
switch (pairing_type) {
- case PairingType::AUTO_CONFIRMATION: {
- auto packet =
- bluetooth::hci::UserConfirmationRequestBuilder::Create(peer, 123456);
- send_event_(std::move(packet));
- } break;
+ case PairingType::AUTO_CONFIRMATION:
+ send_event_(
+ bluetooth::hci::UserConfirmationRequestBuilder::Create(peer, 123456));
+ break;
case PairingType::CONFIRM_Y_N:
- LOG_ALWAYS_FATAL("Unimplemented PairingType %d", static_cast<int>(pairing_type));
+ send_event_(
+ bluetooth::hci::UserConfirmationRequestBuilder::Create(peer, 123456));
break;
case PairingType::DISPLAY_PIN:
- LOG_ALWAYS_FATAL("Unimplemented PairingType %d", static_cast<int>(pairing_type));
+ send_event_(
+ bluetooth::hci::UserConfirmationRequestBuilder::Create(peer, 123456));
break;
case PairingType::DISPLAY_AND_CONFIRM:
- LOG_ALWAYS_FATAL("Unimplemented PairingType %d", static_cast<int>(pairing_type));
+ send_event_(
+ bluetooth::hci::UserConfirmationRequestBuilder::Create(peer, 123456));
break;
case PairingType::INPUT_PIN:
- LOG_ALWAYS_FATAL("Unimplemented PairingType %d", static_cast<int>(pairing_type));
- break;
- case PairingType::INVALID:
- LOG_ALWAYS_FATAL("Unimplemented PairingType %d", static_cast<int>(pairing_type));
+ send_event_(bluetooth::hci::UserPasskeyRequestBuilder::Create(peer));
break;
default:
LOG_ALWAYS_FATAL("Invalid PairingType %d", static_cast<int>(pairing_type));
@@ -999,9 +1075,8 @@
}
bluetooth::hci::ErrorCode LinkLayerController::LinkKeyRequestReply(
- const Address& peer, PacketView<true> key) {
- std::vector<uint8_t> key_vec(key.begin(), key.end());
- security_manager_.WriteKey(peer, key_vec);
+ const Address& peer, const std::array<uint8_t, 16>& key) {
+ security_manager_.WriteKey(peer, key);
security_manager_.AuthenticationRequestFinished();
ScheduleTask(milliseconds(5), [this, peer]() { AuthenticateRemoteStage2(peer); });
@@ -1033,19 +1108,18 @@
PairingType pairing_type = security_manager_.GetSimplePairingType();
if (pairing_type != PairingType::INVALID) {
- ScheduleTask(milliseconds(5), [this, peer, pairing_type]() { AuthenticateRemoteStage1(peer, pairing_type); });
- auto packet = model::packets::IoCapabilityResponseBuilder::Create(
+ ScheduleTask(milliseconds(5), [this, peer, pairing_type]() {
+ AuthenticateRemoteStage1(peer, pairing_type);
+ });
+ SendLinkLayerPacket(model::packets::IoCapabilityResponseBuilder::Create(
properties_.GetAddress(), peer, io_capability, oob_data_present_flag,
- authentication_requirements);
- SendLinkLayerPacket(std::move(packet));
-
+ authentication_requirements));
} else {
LOG_INFO("%s: Requesting remote capability", __func__);
- auto packet = model::packets::IoCapabilityRequestBuilder::Create(
+ SendLinkLayerPacket(model::packets::IoCapabilityRequestBuilder::Create(
properties_.GetAddress(), peer, io_capability, oob_data_present_flag,
- authentication_requirements);
- SendLinkLayerPacket(std::move(packet));
+ authentication_requirements));
}
return bluetooth::hci::ErrorCode::SUCCESS;
@@ -1072,12 +1146,19 @@
return bluetooth::hci::ErrorCode::AUTHENTICATION_FAILURE;
}
// TODO: Key could be calculated here.
- std::vector<uint8_t> key_vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ std::array<uint8_t, 16> key_vec{1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16};
security_manager_.WriteKey(peer, key_vec);
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(milliseconds(5), [this, peer]() { AuthenticateRemoteStage2(peer); });
+ ScheduleTask(milliseconds(5), [this, peer, key_vec]() {
+ send_event_(bluetooth::hci::LinkKeyNotificationBuilder::Create(
+ peer, key_vec, bluetooth::hci::KeyType::AUTHENTICATED_P256));
+ });
+
+ ScheduleTask(milliseconds(15),
+ [this, peer]() { AuthenticateRemoteStage2(peer); });
return bluetooth::hci::ErrorCode::SUCCESS;
}
@@ -1163,8 +1244,15 @@
return;
}
+ uint16_t count = security_manager_.ReadKey(peer);
+ if (count == 0) {
+ LOG_ERROR("NO KEY HERE for %s", peer.ToString().c_str());
+ return;
+ }
+ auto array = security_manager_.GetKey(peer);
+ std::vector<uint8_t> key_vec{array.begin(), array.end()};
auto packet = model::packets::EncryptConnectionBuilder::Create(
- properties_.GetAddress(), peer, security_manager_.GetKey(peer));
+ properties_.GetAddress(), peer, key_vec);
SendLinkLayerPacket(std::move(packet));
}
@@ -1231,11 +1319,8 @@
return bluetooth::hci::ErrorCode::UNKNOWN_CONNECTION;
}
- LOG_INFO("%s: Reject in 200ms", __func__);
- ScheduleTask(milliseconds(200), [this, addr, reason]() {
- LOG_INFO("%s: Reject", __func__);
- RejectSlaveConnection(addr, reason);
- });
+ ScheduleTask(milliseconds(200),
+ [this, addr, reason]() { RejectSlaveConnection(addr, reason); });
return bluetooth::hci::ErrorCode::SUCCESS;
}
@@ -1243,10 +1328,10 @@
void LinkLayerController::RejectSlaveConnection(const Address& addr, uint8_t reason) {
auto to_send = model::packets::PageRejectBuilder::Create(
properties_.GetAddress(), addr, reason);
- LOG_INFO("%s sending page reject to %s", __func__, addr.ToString().c_str());
+ LOG_INFO("%s sending page reject to %s (reason 0x%02hhx)", __func__,
+ addr.ToString().c_str(), reason);
SendLinkLayerPacket(std::move(to_send));
- ASSERT(reason >= 0x0d && reason <= 0x0f);
auto packet = bluetooth::hci::ConnectionCompleteBuilder::Create(
static_cast<bluetooth::hci::ErrorCode>(reason), 0xeff, addr,
bluetooth::hci::LinkType::ACL, bluetooth::hci::Enable::DISABLED);
@@ -1256,10 +1341,10 @@
bluetooth::hci::ErrorCode LinkLayerController::CreateConnection(
const Address& addr, uint16_t, uint8_t, uint16_t,
uint8_t allow_role_switch) {
- if (!connections_.CreatePendingConnection(addr)) {
+ if (!connections_.CreatePendingConnection(
+ addr, properties_.GetAuthenticationEnable() == 1)) {
return bluetooth::hci::ErrorCode::CONTROLLER_BUSY;
}
-
auto page = model::packets::PageBuilder::Create(
properties_.GetAddress(), addr, properties_.GetClassOfDevice(),
allow_role_switch);
@@ -1535,7 +1620,6 @@
void LinkLayerController::StartInquiry(milliseconds timeout) {
ScheduleTask(milliseconds(timeout), [this]() { LinkLayerController::InquiryTimeout(); });
inquiry_state_ = Inquiry::InquiryState::INQUIRY;
- LOG_INFO("InquiryState = %d ", static_cast<int>(inquiry_state_));
}
void LinkLayerController::InquiryCancel() {
@@ -1569,7 +1653,6 @@
if (duration_cast<milliseconds>(now - last_inquiry_) < milliseconds(2000)) {
return;
}
- LOG_INFO("Inquiry ");
auto packet = model::packets::InquiryBuilder::Create(
properties_.GetAddress(), Address::kEmpty, inquiry_mode_);
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
index ffc9044..cffc935 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
@@ -24,9 +24,8 @@
#include "include/phy.h"
#include "model/devices/device_properties.h"
#include "model/setup/async_manager.h"
-#include "packets/hci/acl_packet_view.h"
-#include "packets/hci/sco_packet_view.h"
#include "packets/link_layer_packets.h"
+#include "packets/packet_view.h"
#include "security_manager.h"
namespace test_vendor_lib {
@@ -40,19 +39,19 @@
LinkLayerController(const DeviceProperties& properties) : properties_(properties) {}
bluetooth::hci::ErrorCode SendCommandToRemoteByAddress(
bluetooth::hci::OpCode opcode, packets::PacketView<true> args,
- const Address& remote, bool use_public_address);
+ const Address& remote);
bluetooth::hci::ErrorCode SendCommandToRemoteByHandle(
bluetooth::hci::OpCode opcode, packets::PacketView<true> args,
uint16_t handle);
- hci::Status SendScoToRemote(packets::ScoPacketView sco_packet);
- hci::Status SendAclToRemote(packets::AclPacketView acl_packet);
+ hci::Status SendScoToRemote(bluetooth::hci::ScoPacketView sco_packet);
+ hci::Status SendAclToRemote(bluetooth::hci::AclPacketView acl_packet);
void WriteSimplePairingMode(bool enabled);
void StartSimplePairing(const Address& address);
void AuthenticateRemoteStage1(const Address& address, PairingType pairing_type);
void AuthenticateRemoteStage2(const Address& address);
- bluetooth::hci::ErrorCode LinkKeyRequestReply(const Address& address,
- packets::PacketView<true> key);
+ bluetooth::hci::ErrorCode LinkKeyRequestReply(
+ const Address& address, const std::array<uint8_t, 16>& key);
bluetooth::hci::ErrorCode LinkKeyRequestNegativeReply(const Address& address);
bluetooth::hci::ErrorCode IoCapabilityRequestReply(
const Address& peer, uint8_t io_capability, uint8_t oob_data_present_flag,
@@ -106,9 +105,11 @@
// Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
const std::function<void(
- std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>& send_event_);
+ std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>& send_event);
- void RegisterAclChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_acl);
+ void RegisterAclChannel(
+ const std::function<
+ void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>& send_acl);
void RegisterScoChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_sco);
@@ -261,7 +262,6 @@
std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet);
void IncomingAclPacket(model::packets::LinkLayerPacketView packet);
void IncomingAclAckPacket(model::packets::LinkLayerPacketView packet);
- void IncomingCommandPacket(model::packets::LinkLayerPacketView packet);
void IncomingCreateConnectionPacket(
model::packets::LinkLayerPacketView packet);
void IncomingDisconnectPacket(model::packets::LinkLayerPacketView packet);
@@ -287,7 +287,27 @@
void IncomingPagePacket(model::packets::LinkLayerPacketView packet);
void IncomingPageRejectPacket(model::packets::LinkLayerPacketView packet);
void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet);
- void IncomingResponsePacket(model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteLmpFeatures(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteLmpFeaturesResponse(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteSupportedFeatures(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteSupportedFeaturesResponse(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteExtendedFeatures(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteExtendedFeaturesResponse(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteVersion(model::packets::LinkLayerPacketView packet);
+ void IncomingReadRemoteVersionResponse(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingReadClockOffset(model::packets::LinkLayerPacketView packet);
+ void IncomingReadClockOffsetResponse(
+ model::packets::LinkLayerPacketView packet);
+ void IncomingRemoteNameRequest(model::packets::LinkLayerPacketView packet);
+ void IncomingRemoteNameRequestResponse(
+ model::packets::LinkLayerPacketView packet);
private:
const DeviceProperties& properties_;
@@ -308,7 +328,8 @@
std::function<void(AsyncTaskId)> cancel_task_;
// Callbacks to send packets back to the HCI.
- std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_acl_;
+ std::function<void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>
+ send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>
send_event_;
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
diff --git a/vendor_libs/test_vendor_lib/model/controller/security_manager.cc b/vendor_libs/test_vendor_lib/model/controller/security_manager.cc
index bd3072c..38b9e64 100644
--- a/vendor_libs/test_vendor_lib/model/controller/security_manager.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/security_manager.cc
@@ -44,7 +44,8 @@
return key_store_.count(addr.ToString());
}
-uint16_t SecurityManager::WriteKey(const Address& addr, const std::vector<uint8_t>& key) {
+uint16_t SecurityManager::WriteKey(const Address& addr,
+ const std::array<uint8_t, 16>& key) {
if (key_store_.size() >= max_keys_) {
return 0;
}
@@ -52,7 +53,8 @@
return 1;
}
-const std::vector<uint8_t>& SecurityManager::GetKey(const Address& addr) const {
+const std::array<uint8_t, 16>& SecurityManager::GetKey(
+ const Address& addr) const {
ASSERT_LOG(ReadKey(addr), "No such key");
return key_store_.at(addr.ToString());
}
@@ -130,7 +132,53 @@
if (!(peer_requires_mitm || host_requires_mitm)) {
return PairingType::AUTO_CONFIRMATION;
}
- return PairingType::INVALID;
+ LOG_INFO("%s: host does%s require peer does%s require MITM",
+ peer_address_.ToString().c_str(), host_requires_mitm ? "" : "n't",
+ peer_requires_mitm ? "" : "n't");
+ switch (peer_io_capability_) {
+ case IoCapabilityType::DISPLAY_ONLY:
+ switch (host_io_capability_) {
+ case IoCapabilityType::DISPLAY_ONLY:
+ case IoCapabilityType::DISPLAY_YES_NO:
+ return PairingType::AUTO_CONFIRMATION;
+ case IoCapabilityType::KEYBOARD_ONLY:
+ return PairingType::INPUT_PIN;
+ case IoCapabilityType::NO_INPUT_NO_OUTPUT:
+ return PairingType::AUTO_CONFIRMATION;
+ default:
+ return PairingType::INVALID;
+ }
+ case IoCapabilityType::DISPLAY_YES_NO:
+ switch (host_io_capability_) {
+ case IoCapabilityType::DISPLAY_ONLY:
+ return PairingType::AUTO_CONFIRMATION;
+ case IoCapabilityType::DISPLAY_YES_NO:
+ return PairingType::DISPLAY_AND_CONFIRM;
+ case IoCapabilityType::KEYBOARD_ONLY:
+ return PairingType::DISPLAY_PIN;
+ case IoCapabilityType::NO_INPUT_NO_OUTPUT:
+ return PairingType::AUTO_CONFIRMATION;
+ default:
+ return PairingType::INVALID;
+ }
+ case IoCapabilityType::KEYBOARD_ONLY:
+ switch (host_io_capability_) {
+ case IoCapabilityType::DISPLAY_ONLY:
+ return PairingType::DISPLAY_PIN;
+ case IoCapabilityType::DISPLAY_YES_NO:
+ return PairingType::DISPLAY_PIN;
+ case IoCapabilityType::KEYBOARD_ONLY:
+ return PairingType::INPUT_PIN;
+ case IoCapabilityType::NO_INPUT_NO_OUTPUT:
+ return PairingType::AUTO_CONFIRMATION;
+ default:
+ return PairingType::INVALID;
+ }
+ case IoCapabilityType::NO_INPUT_NO_OUTPUT:
+ return PairingType::AUTO_CONFIRMATION;
+ default:
+ return PairingType::INVALID;
+ }
}
} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/security_manager.h b/vendor_libs/test_vendor_lib/model/controller/security_manager.h
index 8d566ea..e77f1d1 100644
--- a/vendor_libs/test_vendor_lib/model/controller/security_manager.h
+++ b/vendor_libs/test_vendor_lib/model/controller/security_manager.h
@@ -16,10 +16,10 @@
#pragma once
+#include <array>
#include <cstdint>
#include <string>
#include <unordered_map>
-#include <vector>
#include "hci/address.h"
@@ -64,12 +64,10 @@
uint16_t DeleteKey(const Address& addr);
uint16_t ReadAllKeys() const;
uint16_t ReadKey(const Address& addr) const;
- uint16_t WriteKey(const Address& addr, const std::vector<uint8_t>& key);
- uint16_t ReadCapacity() const {
- return max_keys_;
- };
+ uint16_t WriteKey(const Address& addr, const std::array<uint8_t, 16>& key);
+ uint16_t ReadCapacity() const { return max_keys_; };
- const std::vector<uint8_t>& GetKey(const Address& addr) const;
+ const std::array<uint8_t, 16>& GetKey(const Address& addr) const;
void AuthenticationRequest(const Address& addr, uint16_t handle);
void AuthenticationRequestFinished();
@@ -89,16 +87,16 @@
private:
uint16_t max_keys_;
- std::unordered_map<std::string, std::vector<uint8_t>> key_store_;
+ std::unordered_map<std::string, std::array<uint8_t, 16>> key_store_;
bool peer_capabilities_valid_{false};
IoCapabilityType peer_io_capability_;
- bool peer_oob_present_flag_;
+ bool peer_oob_present_flag_{false};
AuthenticationType peer_authentication_requirements_;
bool host_capabilities_valid_{false};
IoCapabilityType host_io_capability_;
- bool host_oob_present_flag_;
+ bool host_oob_present_flag_{false};
AuthenticationType host_authentication_requirements_;
bool authenticating_{false};
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 f3fc3e6..65603f1 100644
--- a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
@@ -31,7 +31,8 @@
page_scan_delay_ms_ = std::chrono::milliseconds(600);
// Stub in packet handling for now
- link_layer_controller_.RegisterAclChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
+ link_layer_controller_.RegisterAclChannel(
+ [](std::shared_ptr<bluetooth::hci::AclPacketBuilder>) {});
link_layer_controller_.RegisterEventChannel(
[](std::shared_ptr<bluetooth::hci::EventPacketBuilder>) {});
link_layer_controller_.RegisterScoChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
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 b9d03ba..2cbd4b0 100644
--- a/vendor_libs/test_vendor_lib/model/devices/device_properties.h
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
@@ -16,6 +16,7 @@
#pragma once
+#include <array>
#include <cstdint>
#include <string>
#include <vector>
@@ -145,12 +146,13 @@
}
void SetName(const std::vector<uint8_t>& name) {
- name_ = name;
+ name_.fill(0);
+ for (size_t i = 0; i < 248 && i < name.size(); i++) {
+ name_[i] = name[i];
+ }
}
- const std::vector<uint8_t>& GetName() const {
- return name_;
- }
+ const std::array<uint8_t, 248>& GetName() const { return name_; }
void SetExtendedInquiryData(const std::vector<uint8_t>& eid) {
extended_inquiry_data_ = eid;
@@ -315,7 +317,7 @@
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_;
+ std::array<uint8_t, 248> name_;
Address address_;
uint8_t page_scan_repetition_mode_;
uint16_t clock_offset_;
diff --git a/vendor_libs/test_vendor_lib/packets/Android.bp b/vendor_libs/test_vendor_lib/packets/Android.bp
index d25a11f..a769e14 100644
--- a/vendor_libs/test_vendor_lib/packets/Android.bp
+++ b/vendor_libs/test_vendor_lib/packets/Android.bp
@@ -14,13 +14,9 @@
"packet_view.cc",
"raw_builder.cc",
"view.cc",
- "hci/acl_packet_builder.cc",
- "hci/acl_packet_view.cc",
"hci/command_packet_builder.cc",
"hci/command_packet_view.cc",
"hci/hci_packet_builder.cc",
- "hci/sco_packet_builder.cc",
- "hci/sco_packet_view.cc",
],
cflags: [
"-fvisibility=hidden",
@@ -53,7 +49,6 @@
srcs: [
"test/packet_builder_test.cc",
"test/packet_view_test.cc",
- "hci/test/acl_builder_test.cc",
":BluetoothHciClassSources",
],
header_libs: [
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc
deleted file mode 100644
index 3c74ad6..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018 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 "packets/hci/acl_packet_builder.h"
-
-#include "os/log.h"
-
-using std::vector;
-using test_vendor_lib::acl::BroadcastFlagsType;
-using test_vendor_lib::acl::PacketBoundaryFlagsType;
-
-namespace test_vendor_lib {
-namespace packets {
-
-AclPacketBuilder::AclPacketBuilder(uint16_t handle, PacketBoundaryFlagsType packet_boundary_flags,
- BroadcastFlagsType broadcast_flags, std::unique_ptr<BasePacketBuilder> payload)
- : handle_(handle), packet_boundary_flags_(packet_boundary_flags), broadcast_flags_(broadcast_flags),
- payload_(std::move(payload)) {}
-
-std::unique_ptr<AclPacketBuilder> AclPacketBuilder::Create(uint16_t handle,
- PacketBoundaryFlagsType packet_boundary_flags,
- BroadcastFlagsType broadcast_flags,
- std::unique_ptr<BasePacketBuilder> payload) {
- return std::unique_ptr<AclPacketBuilder>(
- new AclPacketBuilder(handle, packet_boundary_flags, broadcast_flags, std::move(payload)));
-}
-
-size_t AclPacketBuilder::size() const {
- return 2 * sizeof(uint16_t) + payload_->size();
-}
-
-void AclPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
- insert(static_cast<uint16_t>((handle_ & 0xfff) | (static_cast<uint16_t>(packet_boundary_flags_) << 12) |
- (static_cast<uint16_t>(broadcast_flags_) << 14)),
- it);
- uint16_t payload_size = payload_->size();
-
- ASSERT_LOG(static_cast<size_t>(payload_size) == payload_->size(), "Payload too large for an ACL packet: %d",
- static_cast<int>(payload_->size()));
- insert(payload_size, it);
- payload_->Serialize(it);
-}
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h
deleted file mode 100644
index 9599130..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "include/acl.h"
-#include "packets/hci/hci_packet_builder.h"
-#include "packets/packet_builder.h"
-
-namespace test_vendor_lib {
-namespace packets {
-
-// ACL data packets are specified in the Bluetooth Core Specification Version
-// 4.2, Volume 2, Part E, Section 5.4.2
-class AclPacketBuilder : public HciPacketBuilder {
- public:
- virtual ~AclPacketBuilder() override = default;
-
- static std::unique_ptr<AclPacketBuilder> Create(uint16_t handle, acl::PacketBoundaryFlagsType packet_boundary_flags,
- acl::BroadcastFlagsType broadcast_flags,
- std::unique_ptr<BasePacketBuilder> payload);
-
- virtual size_t size() const override;
- virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const;
-
- private:
- AclPacketBuilder(uint16_t handle, acl::PacketBoundaryFlagsType packet_boundary_flags,
- acl::BroadcastFlagsType broadcast_flags, std::unique_ptr<BasePacketBuilder> payload);
- AclPacketBuilder() = delete;
- uint16_t handle_;
- acl::PacketBoundaryFlagsType packet_boundary_flags_;
- acl::BroadcastFlagsType broadcast_flags_;
- std::unique_ptr<BasePacketBuilder> payload_;
-};
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc
deleted file mode 100644
index 4e41a73..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2018 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 "packets/hci/acl_packet_view.h"
-
-#include "os/log.h"
-
-using std::vector;
-using test_vendor_lib::acl::BroadcastFlagsType;
-using test_vendor_lib::acl::PacketBoundaryFlagsType;
-
-namespace test_vendor_lib {
-namespace packets {
-
-AclPacketView::AclPacketView(std::shared_ptr<std::vector<uint8_t>> packet) : PacketView<true>(packet) {}
-
-AclPacketView::AclPacketView(PacketView<true> packet_view) : PacketView<true>(packet_view) {}
-
-AclPacketView AclPacketView::Create(std::shared_ptr<std::vector<uint8_t>> packet) {
- return AclPacketView(packet);
-}
-
-AclPacketView AclPacketView::Create(PacketView<true> packet_view) {
- return AclPacketView(packet_view);
-}
-
-uint16_t AclPacketView::GetHandle() const {
- return begin().extract<uint16_t>() & 0xfff;
-}
-
-PacketBoundaryFlagsType AclPacketView::GetPacketBoundaryFlags() const {
- return static_cast<PacketBoundaryFlagsType>(((begin() + 1).extract<uint8_t>() & 0x30) >> 4);
-}
-
-BroadcastFlagsType AclPacketView::GetBroadcastFlags() const {
- return static_cast<BroadcastFlagsType>(((begin() + 1).extract<uint8_t>() & 0xc0) >> 6);
-}
-
-PacketView<true> AclPacketView::GetPayload() const {
- uint16_t payload_size = (begin() + sizeof(uint16_t)).extract<uint16_t>();
- ASSERT_LOG(static_cast<uint16_t>(size() - 2 * sizeof(uint16_t)) == payload_size,
- "Malformed ACL packet payload_size %d + 4 != %d", static_cast<int>(payload_size),
- static_cast<int>(size()));
- return SubViewLittleEndian(2 * sizeof(uint16_t), size());
-}
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h
deleted file mode 100644
index 1e69cda..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "include/acl.h"
-#include "packets/packet_view.h"
-
-namespace test_vendor_lib {
-namespace packets {
-
-// ACL data packets are specified in the Bluetooth Core Specification Version
-// 4.2, Volume 2, Part E, Section 5.4.2
-class AclPacketView : public PacketView<true> {
- public:
- virtual ~AclPacketView() override = default;
-
- static AclPacketView Create(std::shared_ptr<std::vector<uint8_t>> packet);
- static AclPacketView Create(PacketView<true> packet_view);
-
- uint16_t GetHandle() const;
- acl::PacketBoundaryFlagsType GetPacketBoundaryFlags() const;
- acl::BroadcastFlagsType GetBroadcastFlags() const;
- PacketView<true> GetPayload() const;
-
- private:
- AclPacketView(std::shared_ptr<std::vector<uint8_t>> packet);
- AclPacketView(PacketView<true> packet_view);
- AclPacketView() = delete;
-};
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc
deleted file mode 100644
index ae61124..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2018 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 "packets/hci/sco_packet_builder.h"
-
-#include "os/log.h"
-
-using std::vector;
-using test_vendor_lib::sco::PacketStatusFlagsType;
-
-namespace test_vendor_lib {
-namespace packets {
-
-ScoPacketBuilder::ScoPacketBuilder(uint16_t handle, PacketStatusFlagsType packet_status_flags,
- std::unique_ptr<BasePacketBuilder> payload)
- : handle_(handle), packet_status_flags_(packet_status_flags), payload_(std::move(payload)) {}
-
-size_t ScoPacketBuilder::size() const {
- return 2 * sizeof(uint16_t) + payload_->size();
-}
-
-void ScoPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
- insert(static_cast<uint16_t>((handle_ & 0xfff) | (static_cast<uint16_t>(packet_status_flags_) << 12)), it);
- uint8_t payload_size = payload_->size();
-
- ASSERT_LOG(static_cast<size_t>(payload_size) == payload_->size(), "Payload too large for a SCO packet: %d",
- static_cast<int>(payload_->size()));
- insert(payload_size, it);
- payload_->Serialize(it);
-}
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h
deleted file mode 100644
index 94a71f5..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "include/sco.h"
-#include "packets/hci/hci_packet_builder.h"
-#include "packets/packet_builder.h"
-
-namespace test_vendor_lib {
-namespace packets {
-
-// SCO data packets are specified in the Bluetooth Core Specification Version
-// 4.2, Volume 2, Part E, Section 5.4.3
-class ScoPacketBuilder : public HciPacketBuilder {
- public:
- virtual ~ScoPacketBuilder() override = default;
-
- static std::unique_ptr<ScoPacketBuilder> Create(uint16_t handle, sco::PacketStatusFlagsType packet_status_flags,
- std::unique_ptr<BasePacketBuilder> payload);
-
- virtual size_t size() const override;
-
- virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
-
- private:
- ScoPacketBuilder(uint16_t handle, sco::PacketStatusFlagsType packet_status_flags,
- std::unique_ptr<BasePacketBuilder> payload);
- ScoPacketBuilder() = delete;
- uint16_t handle_;
- sco::PacketStatusFlagsType packet_status_flags_;
- std::unique_ptr<BasePacketBuilder> payload_;
-};
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc
deleted file mode 100644
index 415ce05..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018 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 "packets/hci/sco_packet_view.h"
-
-#include "os/log.h"
-
-using test_vendor_lib::sco::PacketStatusFlagsType;
-
-namespace test_vendor_lib {
-namespace packets {
-
-ScoPacketView::ScoPacketView(std::shared_ptr<std::vector<uint8_t>> packet) : PacketView<true>(packet) {}
-
-ScoPacketView ScoPacketView::Create(std::shared_ptr<std::vector<uint8_t>> packet) {
- return ScoPacketView(packet);
-}
-
-uint16_t ScoPacketView::GetHandle() const {
- return begin().extract<uint16_t>() & 0xfff;
-}
-
-PacketStatusFlagsType ScoPacketView::GetPacketStatusFlags() const {
- return static_cast<PacketStatusFlagsType>(((begin() + 1).extract<uint8_t>() & 0x30) >> 4);
-}
-
-PacketView<true> ScoPacketView::GetPayload() const {
- uint8_t payload_size = (begin() + sizeof(uint16_t)).extract<uint8_t>();
- ASSERT_LOG(static_cast<uint8_t>(size() - sizeof(uint16_t) - sizeof(uint8_t)) == payload_size,
- "Malformed SCO packet payload_size %d + 4 != %d", static_cast<int>(payload_size),
- static_cast<int>(size()));
- return SubViewLittleEndian(sizeof(uint16_t) + sizeof(uint8_t), size());
-}
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h
deleted file mode 100644
index 3fb24b0..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "include/sco.h"
-#include "packets/packet_view.h"
-
-namespace test_vendor_lib {
-namespace packets {
-
-// SCO data packets are specified in the Bluetooth Core Specification Version
-// 4.2, Volume 2, Part E, Section 5.4.3
-class ScoPacketView : public PacketView<true> {
- public:
- virtual ~ScoPacketView() override = default;
-
- static ScoPacketView Create(std::shared_ptr<std::vector<uint8_t>> packet);
-
- uint16_t GetHandle() const;
- sco::PacketStatusFlagsType GetPacketStatusFlags() const;
- PacketView<true> GetPayload() const;
-
- private:
- ScoPacketView(std::shared_ptr<std::vector<uint8_t>> packet);
- ScoPacketView() = delete;
-};
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc b/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc
deleted file mode 100644
index ad99df1..0000000
--- a/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2018 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 "packets/hci/acl_packet_builder.h"
-#include "packets/hci/acl_packet_view.h"
-#include "packets/raw_builder.h"
-
-#include <gtest/gtest.h>
-#include <forward_list>
-#include <memory>
-
-#include "hci/address.h"
-
-using ::bluetooth::hci::Address;
-using std::vector;
-using test_vendor_lib::acl::BroadcastFlagsType;
-using test_vendor_lib::acl::PacketBoundaryFlagsType;
-
-namespace {
-vector<uint8_t> count = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-};
-
-vector<uint8_t> information_request = {
- 0xfe, 0x2e, 0x0a, 0x00, 0x06, 0x00, 0x01, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x02, 0x00,
-};
-
-} // namespace
-
-namespace test_vendor_lib {
-namespace packets {
-
-class AclBuilderTest : public ::testing::Test {
- public:
- AclBuilderTest() = default;
- ~AclBuilderTest() override = default;
-};
-
-TEST(AclBuilderTest, buildAclCountTest) {
- uint16_t handle = 0x0102;
- PacketBoundaryFlagsType packet_boundary_flags = PacketBoundaryFlagsType::FIRST_AUTOMATICALLY_FLUSHABLE;
- BroadcastFlagsType broadcast_flags = BroadcastFlagsType::ACTIVE_SLAVE_BROADCAST;
-
- std::unique_ptr<RawBuilder> count_payload = std::make_unique<RawBuilder>();
- count_payload->AddOctets(count);
- ASSERT_EQ(count.size(), count_payload->size());
-
- std::unique_ptr<AclPacketBuilder> count_packet =
- AclPacketBuilder::Create(handle, packet_boundary_flags, broadcast_flags, std::move(count_payload));
-
- ASSERT_EQ(count.size() + 4, count_packet->size());
-
- std::shared_ptr<std::vector<uint8_t>> count_packet_bytes = count_packet->ToVector();
- AclPacketView count_packet_view = AclPacketView::Create(count_packet_bytes);
-
- ASSERT_EQ(handle, count_packet_view.GetHandle());
- ASSERT_EQ(packet_boundary_flags, count_packet_view.GetPacketBoundaryFlags());
- ASSERT_EQ(broadcast_flags, count_packet_view.GetBroadcastFlags());
- PacketView<true> count_view = count_packet_view.GetPayload();
-
- ASSERT_EQ(count_view.size(), count.size());
- for (size_t i = 0; i < count_view.size(); i++) {
- ASSERT_EQ(count_view[i], count[i]);
- }
-}
-
-TEST(AclBuilderTest, buildInformationRequest) {
- uint16_t handle = 0x0efe;
- PacketBoundaryFlagsType packet_boundary_flags = PacketBoundaryFlagsType::FIRST_AUTOMATICALLY_FLUSHABLE;
- BroadcastFlagsType broadcast_flags = BroadcastFlagsType::POINT_TO_POINT;
-
- std::vector<uint8_t> payload_bytes(information_request.begin() + 4, information_request.end());
- std::unique_ptr<RawBuilder> payload = std::make_unique<RawBuilder>();
- payload->AddOctets(payload_bytes);
- ASSERT_EQ(payload_bytes.size(), payload->size());
-
- std::unique_ptr<AclPacketBuilder> packet =
- AclPacketBuilder::Create(handle, packet_boundary_flags, broadcast_flags, std::move(payload));
-
- ASSERT_EQ(information_request.size(), packet->size());
-
- std::shared_ptr<std::vector<uint8_t>> packet_bytes = packet->ToVector();
- AclPacketView packet_view = AclPacketView::Create(packet_bytes);
-
- ASSERT_EQ(packet_bytes->size(), information_request.size());
- for (size_t i = 0; i < packet_bytes->size(); i++) {
- ASSERT_EQ((*packet_bytes)[i], information_request[i]);
- }
-
- ASSERT_EQ(handle, packet_view.GetHandle());
- ASSERT_EQ(packet_boundary_flags, packet_view.GetPacketBoundaryFlags());
- ASSERT_EQ(broadcast_flags, packet_view.GetBroadcastFlags());
- PacketView<true> payload_view = packet_view.GetPayload();
-
- ASSERT_EQ(payload_view.size(), payload_bytes.size());
- for (size_t i = 0; i < payload_view.size(); i++) {
- ASSERT_EQ(payload_view[i], payload_bytes[i]);
- }
-
- ASSERT_EQ(packet_view.size(), information_request.size());
- for (size_t i = 0; i < packet_view.size(); i++) {
- ASSERT_EQ(packet_view[i], information_request[i]);
- }
-}
-
-} // namespace packets
-} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl b/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl
index 0c27d97..2d601cd 100644
--- a/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl
+++ b/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl
@@ -227,8 +227,7 @@
}
packet RemoteNameRequestResponse : LinkLayerPacket (type = REMOTE_NAME_REQUEST_RESPONSE) {
- _size_(name) : 8,
- name : 8[],
+ name : 8[248],
}
packet ScoPacket : LinkLayerPacket (type = SCO) {
diff --git a/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc b/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc
index 13aab3c..9c19c4f 100644
--- a/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc
+++ b/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc
@@ -16,22 +16,20 @@
*
******************************************************************************/
-#include <gtest/gtest.h>
-#include <string>
-#include <vector>
-using std::vector;
-
#include "model/controller/security_manager.h"
+#include <gtest/gtest.h>
+#include <array>
+#include <string>
+
namespace {
const std::string kTestAddr1 = "12:34:56:78:9a:bc";
const std::string kTestAddr2 = "cb:a9:87:65:43:21";
const std::string kTestAddr3 = "cb:a9:56:78:9a:bc";
const std::string kTestAddr4 = "12:34:56:78:9a:bc";
-const vector<uint8_t> kZeros_octets = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const vector<uint8_t> kTestAddr1_octets = {0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12};
-const vector<uint8_t> kTestKey = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
+const std::array<uint8_t, 16> kTestKey = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x0e, 0x0f, 0x10};
} // namespace
namespace test_vendor_lib {