Merge changes I83e8e7b4,I12bade3d
* changes:
Rootcanal: Use PDL to parse incoming commands
HCI: Implement 36 Le commands and events
diff --git a/gd/l2cap/classic/cert/cert.cc b/gd/l2cap/classic/cert/cert.cc
index abb3561..4f28319 100644
--- a/gd/l2cap/classic/cert/cert.cc
+++ b/gd/l2cap/classic/cert/cert.cc
@@ -164,10 +164,10 @@
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->tx_window_size_ = 5;
+ option->max_transmit_ = 1;
+ option->retransmission_time_out_ = 1000;
+ option->monitor_time_out_ = 2000;
option->maximum_pdu_size_ = 1010;
config.push_back(std::move(option));
}
@@ -407,6 +407,16 @@
LogEvent(response);
break;
}
+ case CommandCode::DISCONNECTION_REQUEST: {
+ DisconnectionRequestView view = DisconnectionRequestView::Create(control_view);
+ ASSERT(view.IsValid());
+ FetchL2capLogResponse response;
+ response.mutable_disconnection_request()->set_signal_id(control_view.GetIdentifier());
+ response.mutable_disconnection_request()->set_dcid(view.GetDestinationCid());
+ response.mutable_disconnection_request()->set_scid(view.GetSourceCid());
+ LogEvent(response);
+ break;
+ }
case CommandCode::DISCONNECTION_RESPONSE: {
DisconnectionResponseView view = DisconnectionResponseView::Create(control_view);
ASSERT(view.IsValid());
diff --git a/gd/l2cap/classic/cert/simple_l2cap_test.py b/gd/l2cap/classic/cert/simple_l2cap_test.py
index 607cfb2..3320694 100644
--- a/gd/l2cap/classic/cert/simple_l2cap_test.py
+++ b/gd/l2cap/classic/cert/simple_l2cap_test.py
@@ -142,6 +142,7 @@
self.cert_device.l2cap.SendConfigurationResponse(l2cap_cert_pb2.ConfigurationResponse(
scid=dcid,
signal_id=log.signal_id,
+ retransmission_config=l2cap_cert_pb2.ChannelRetransmissionFlowControlConfig(mode=self.retransmission_mode)
))
log_event_handler.on(is_configuration_request, handle_configuration_request)
@@ -404,3 +405,55 @@
assert info_response[0][0] == signal_id
assert info_response[0][1] == expected_log_type
assert info_response[0][2] | expected_mask == expected_mask
+
+ def test_transmit_i_frames(self):
+ """
+ L2CAP/ERM/BV-01-C [Transmit I-frames]
+ """
+ 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.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+ self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=1, s=0))
+ self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+ self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=2, s=0))
+ self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+ self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=3, s=0))
+ data_received = []
+ event_handler = EventHandler()
+ def on_data_received(log):
+ log = log.data_packet
+ 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 len(data_received) == 3
+
+ def test_s_frame_transmissions_exceed_max_transmit(self):
+ """
+ L2CAP/ERM/BV-11-C [S-Frame Transmissions Exceed MaxTransmit]
+ """
+ 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.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+ # Retransmission timer = 1, 1 * monitor timer = 2, so total timeout is 3
+ time.sleep(4)
+ disconnect_request = []
+ event_handler = EventHandler()
+
+ def on_disconnect_req(log):
+ log = log.disconnection_request
+ disconnect_request.append((log.dcid, log.scid))
+ event_handler.on(is_disconnection_request, on_disconnect_req)
+
+ logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+ event_handler.execute(logs)
+ assert len(disconnect_request) == 1, "No disconnect request received"
+ assert disconnect_request[0] == (scid, self.scid_dcid_map[scid]), "Incorrect disconnect request received: scid %r, dcid %r" % (disconnect_request[0][0], disconnect_request[0][1])
diff --git a/gd/l2cap/classic/dynamic_channel.h b/gd/l2cap/classic/dynamic_channel.h
new file mode 100644
index 0000000..0bd5a82
--- /dev/null
+++ b/gd/l2cap/classic/dynamic_channel.h
@@ -0,0 +1,29 @@
+/*
+ * 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/dynamic_channel.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace classic {
+
+using DynamicChannel = l2cap::DynamicChannel;
+
+} // namespace classic
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/dynamic_channel_manager.h b/gd/l2cap/classic/dynamic_channel_manager.h
index 4810270..340d68d 100644
--- a/gd/l2cap/classic/dynamic_channel_manager.h
+++ b/gd/l2cap/classic/dynamic_channel_manager.h
@@ -19,9 +19,9 @@
#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/dynamic_channel.h"
#include "l2cap/l2cap_packets.h"
#include "l2cap/psm.h"
#include "l2cap/security_policy.h"
diff --git a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
index 672d24b..2fcf3fc 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
@@ -18,10 +18,10 @@
#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"
-#include "l2cap/dynamic_channel.h"
namespace bluetooth {
namespace l2cap {
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index a23f5ec..142e32e 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -34,8 +34,9 @@
DynamicChannelServiceManagerImpl* dynamic_service_manager,
FixedChannelServiceManagerImpl* fixed_service_manager)
: l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
- data_pipeline_manager_(l2cap_handler, acl_connection_->GetAclQueueEnd()), parameter_provider_(parameter_provider),
- dynamic_service_manager_(dynamic_service_manager), fixed_service_manager_(fixed_service_manager),
+ data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()),
+ parameter_provider_(parameter_provider), dynamic_service_manager_(dynamic_service_manager),
+ fixed_service_manager_(fixed_service_manager),
signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_,
&dynamic_channel_allocator_, fixed_service_manager_) {
ASSERT(l2cap_handler_ != nullptr);
@@ -91,6 +92,7 @@
auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
if (channel != nullptr) {
data_pipeline_manager_.AttachChannel(channel->GetCid(), channel);
+ RefreshRefCount();
}
channel->local_initiated_ = false;
return channel;
@@ -101,6 +103,7 @@
auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
if (channel != nullptr) {
data_pipeline_manager_.AttachChannel(channel->GetCid(), channel);
+ RefreshRefCount();
}
channel->local_initiated_ = true;
return channel;
@@ -118,6 +121,7 @@
}
data_pipeline_manager_.DetachChannel(cid);
dynamic_channel_allocator_.FreeChannel(cid);
+ RefreshRefCount();
}
void Link::RefreshRefCount() {
diff --git a/gd/l2cap/classic/internal/signalling_manager.h b/gd/l2cap/classic/internal/signalling_manager.h
index 81c8c31..3ae95dd 100644
--- a/gd/l2cap/classic/internal/signalling_manager.h
+++ b/gd/l2cap/classic/internal/signalling_manager.h
@@ -112,7 +112,6 @@
l2cap::internal::DynamicChannelAllocator* channel_allocator_;
FixedChannelServiceManagerImpl* fixed_service_manager_;
std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_;
- PendingCommand last_sent_command_;
std::queue<PendingCommand> pending_commands_;
os::Alarm alarm_;
SignalId next_signal_id_ = kInitialSignalId;
diff --git a/gd/l2cap/internal/data_pipeline_manager.cc b/gd/l2cap/internal/data_pipeline_manager.cc
index 1c8d973..674df95 100644
--- a/gd/l2cap/internal/data_pipeline_manager.cc
+++ b/gd/l2cap/internal/data_pipeline_manager.cc
@@ -29,7 +29,7 @@
void DataPipelineManager::AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel) {
ASSERT(sender_map_.find(cid) == sender_map_.end());
sender_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
- std::forward_as_tuple(handler_, scheduler_.get(), channel));
+ std::forward_as_tuple(handler_, link_, scheduler_.get(), channel));
}
void DataPipelineManager::DetachChannel(Cid cid) {
diff --git a/gd/l2cap/internal/data_pipeline_manager.h b/gd/l2cap/internal/data_pipeline_manager.h
index fffbfc7..557a741 100644
--- a/gd/l2cap/internal/data_pipeline_manager.h
+++ b/gd/l2cap/internal/data_pipeline_manager.h
@@ -39,11 +39,12 @@
namespace bluetooth {
namespace l2cap {
namespace internal {
+class ILink;
/**
* Manages data pipeline from channel queue end to link queue end, per link.
* Contains a Scheduler and Receiver per link.
- * Contains a Sender and its corrsponding DataController per attached channel.
+ * Contains a Sender and its corresponding DataController per attached channel.
*/
class DataPipelineManager {
public:
@@ -54,8 +55,8 @@
using LowerDequeue = UpperEnqueue;
using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>;
- DataPipelineManager(os::Handler* handler, LowerQueueUpEnd* link_queue_up_end)
- : handler_(handler), scheduler_(std::make_unique<Fifo>(this, link_queue_up_end, handler)),
+ DataPipelineManager(os::Handler* handler, ILink* link, LowerQueueUpEnd* link_queue_up_end)
+ : handler_(handler), link_(link), scheduler_(std::make_unique<Fifo>(this, link_queue_up_end, handler)),
receiver_(link_queue_up_end, handler, this) {}
virtual void AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel);
@@ -67,6 +68,7 @@
private:
os::Handler* handler_;
+ ILink* link_;
std::unique_ptr<Scheduler> scheduler_;
Receiver receiver_;
std::unordered_map<Cid, Sender> sender_map_;
diff --git a/gd/l2cap/internal/data_pipeline_manager_mock.h b/gd/l2cap/internal/data_pipeline_manager_mock.h
index f5a24f4..9c2f6c8 100644
--- a/gd/l2cap/internal/data_pipeline_manager_mock.h
+++ b/gd/l2cap/internal/data_pipeline_manager_mock.h
@@ -32,7 +32,7 @@
class MockDataPipelineManager : public DataPipelineManager {
public:
MockDataPipelineManager(os::Handler* handler, LowerQueueUpEnd* link_queue_up_end)
- : DataPipelineManager(handler, link_queue_up_end) {}
+ : DataPipelineManager(handler, nullptr, link_queue_up_end) {}
MOCK_METHOD(void, AttachChannel, (Cid, std::shared_ptr<ChannelImpl>), (override));
MOCK_METHOD(void, DetachChannel, (Cid), (override));
MOCK_METHOD(DataController*, GetDataController, (Cid), (override));
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 97f9702..74e8a2f 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
@@ -21,6 +21,7 @@
#include <vector>
#include "common/bind.h"
+#include "l2cap/internal/ilink.h"
#include "os/alarm.h"
#include "packet/fragmenting_inserter.h"
#include "packet/raw_builder.h"
@@ -28,10 +29,10 @@
namespace bluetooth {
namespace l2cap {
namespace internal {
-ErtmController::ErtmController(Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
- Scheduler* scheduler)
- : cid_(cid), remote_cid_(remote_cid), enqueue_buffer_(channel_queue_end), handler_(handler), scheduler_(scheduler),
- pimpl_(std::make_unique<impl>(this, handler)) {}
+ErtmController::ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end,
+ os::Handler* handler, Scheduler* scheduler)
+ : link_(link), cid_(cid), remote_cid_(remote_cid), enqueue_buffer_(channel_queue_end), handler_(handler),
+ scheduler_(scheduler), pimpl_(std::make_unique<impl>(this, handler)) {}
ErtmController::~ErtmController() = default;
@@ -153,7 +154,7 @@
send_rr_or_rnr(Poll::POLL);
// send rr or rnr(p=1)
retry_count_ = 1;
- start_retrans_timer();
+ start_monitor_timer();
tx_state_ = TxState::WAIT_F;
}
}
@@ -770,7 +771,7 @@
}
void CloseChannel() {
- // TODO: Needs a reference to signaller
+ controller_->close_channel();
}
void pop_srej_list() {
@@ -1005,7 +1006,7 @@
}
void ErtmController::close_channel() {
- // TODO: Get a reference to signalling manager
+ link_->SendDisconnectionRequest(cid_, remote_cid_);
}
size_t ErtmController::CopyablePacketBuilder::size() const {
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 dd1ca64..184d6c1 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
@@ -36,13 +36,14 @@
namespace bluetooth {
namespace l2cap {
namespace internal {
+class ILink;
class ErtmController : public DataController {
public:
using UpperEnqueue = packet::PacketView<packet::kLittleEndian>;
using UpperDequeue = packet::BasePacketBuilder;
using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
- ErtmController(Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
+ ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
Scheduler* scheduler);
~ErtmController();
// Segmentation is handled here
@@ -53,6 +54,7 @@
void SetRetransmissionAndFlowControlOptions(const RetransmissionAndFlowControlConfigurationOption& option) override;
private:
+ ILink* link_;
Cid cid_;
Cid remote_cid_;
os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
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
index e1b5818..f813898 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
@@ -18,6 +18,7 @@
#include <gtest/gtest.h>
+#include "l2cap/internal/ilink_mock.h"
#include "l2cap/internal/scheduler_mock.h"
#include "l2cap/l2cap_packets.h"
#include "packet/raw_builder.h"
@@ -73,7 +74,8 @@
TEST_F(ErtmDataControllerTest, transmit_no_fcs) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
auto next_packet = controller.GetNextPacket();
@@ -95,7 +97,8 @@
TEST_F(ErtmDataControllerTest, receive_no_fcs) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 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));
@@ -111,7 +114,8 @@
TEST_F(ErtmDataControllerTest, reassemble_valid_sdu) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
auto segment1 = CreateSdu({'a'});
auto segment2 = CreateSdu({'b', 'c'});
auto segment3 = CreateSdu({'d', 'e', 'f'});
@@ -133,10 +137,11 @@
EXPECT_EQ(data, "abcdef");
}
-TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame) {
+TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame_will_disconnect) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
auto segment1 = CreateSdu({'a'});
auto segment2 = CreateSdu({'b', 'c'});
auto segment3 = CreateSdu({'d', 'e', 'f'});
@@ -150,6 +155,7 @@
auto builder3 = EnhancedInformationFrameBuilder::Create(1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END,
std::move(segment3));
base_view = GetPacketView(std::move(builder3));
+ EXPECT_CALL(link, SendDisconnectionRequest(1, 1));
controller.OnPdu(base_view);
sync_handler(queue_handler_);
auto payload = channel_queue.GetUpEnd()->TryDequeue();
@@ -159,7 +165,8 @@
TEST_F(ErtmDataControllerTest, transmit_with_fcs) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
controller.EnableFcs(true);
EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
@@ -182,7 +189,8 @@
TEST_F(ErtmDataControllerTest, receive_packet_with_fcs) {
common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
testing::MockScheduler scheduler;
- ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+ testing::MockILink link;
+ ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
controller.EnableFcs(true);
auto segment = CreateSdu({'a', 'b', 'c', 'd'});
auto builder = EnhancedInformationFrameWithFcsBuilder::Create(
diff --git a/gd/l2cap/internal/ilink_mock.h b/gd/l2cap/internal/ilink_mock.h
new file mode 100644
index 0000000..15c642b
--- /dev/null
+++ b/gd/l2cap/internal/ilink_mock.h
@@ -0,0 +1,38 @@
+/*
+ * 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/internal/ilink.h"
+
+#include <gmock/gmock.h>
+
+// Unit test interfaces
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace testing {
+
+class MockILink : public ILink {
+ public:
+ MOCK_METHOD(hci::AddressWithType, GetDevice, (), (override));
+ MOCK_METHOD(void, SendDisconnectionRequest, (Cid, Cid), (override));
+};
+
+} // namespace testing
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/internal/sender.cc b/gd/l2cap/internal/sender.cc
index 1c146cf..d4884b2 100644
--- a/gd/l2cap/internal/sender.cc
+++ b/gd/l2cap/internal/sender.cc
@@ -28,9 +28,9 @@
namespace l2cap {
namespace internal {
-Sender::Sender(os::Handler* handler, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel)
- : handler_(handler), queue_end_(channel->GetQueueDownEnd()), scheduler_(scheduler), channel_id_(channel->GetCid()),
- remote_channel_id_(channel->GetRemoteCid()),
+Sender::Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel)
+ : handler_(handler), link_(link), queue_end_(channel->GetQueueDownEnd()), scheduler_(scheduler),
+ channel_id_(channel->GetCid()), remote_channel_id_(channel->GetRemoteCid()),
data_controller_(std::make_unique<BasicModeDataController>(channel_id_, remote_channel_id_, queue_end_, handler_,
scheduler_)) {
try_register_dequeue();
@@ -82,7 +82,7 @@
}
if (mode == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
data_controller_ =
- std::make_unique<ErtmController>(channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
+ std::make_unique<ErtmController>(link_, channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
data_controller_->SetRetransmissionAndFlowControlOptions(config.local_retransmission_and_flow_control_);
data_controller_->EnableFcs(config.fcs_type_ == FcsType::DEFAULT);
return;
diff --git a/gd/l2cap/internal/sender.h b/gd/l2cap/internal/sender.h
index 46e0006..0e8e78d 100644
--- a/gd/l2cap/internal/sender.h
+++ b/gd/l2cap/internal/sender.h
@@ -37,6 +37,7 @@
namespace l2cap {
namespace internal {
class Scheduler;
+class ILink;
/**
* A middle layer between L2CAP channel and outgoing packet scheduler.
@@ -48,7 +49,7 @@
using UpperDequeue = packet::BasePacketBuilder;
using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
- Sender(os::Handler* handler, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel);
+ Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel);
~Sender();
/**
@@ -67,6 +68,7 @@
private:
os::Handler* handler_;
+ ILink* link_;
UpperQueueDownEnd* queue_end_;
Scheduler* scheduler_;
const Cid channel_id_;
diff --git a/gd/l2cap/internal/sender_test.cc b/gd/l2cap/internal/sender_test.cc
index cecdfa4..bd24fd4 100644
--- a/gd/l2cap/internal/sender_test.cc
+++ b/gd/l2cap/internal/sender_test.cc
@@ -77,7 +77,7 @@
EXPECT_CALL(*mock_channel_, GetQueueDownEnd()).WillRepeatedly(Return(channel_queue_.GetDownEnd()));
EXPECT_CALL(*mock_channel_, GetCid()).WillRepeatedly(Return(cid_));
EXPECT_CALL(*mock_channel_, GetRemoteCid()).WillRepeatedly(Return(cid_));
- sender_ = new Sender(queue_handler_, &scheduler_, mock_channel_);
+ sender_ = new Sender(queue_handler_, nullptr, &scheduler_, mock_channel_);
}
void TearDown() override {
diff --git a/gd/l2cap/le/dynamic_channel.h b/gd/l2cap/le/dynamic_channel.h
new file mode 100644
index 0000000..db1d822
--- /dev/null
+++ b/gd/l2cap/le/dynamic_channel.h
@@ -0,0 +1,29 @@
+/*
+ * 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/dynamic_channel.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace le {
+
+using DynamicChannel = l2cap::DynamicChannel;
+
+} // namespace le
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/le/internal/link.h b/gd/l2cap/le/internal/link.h
index 2807353..945f54a 100644
--- a/gd/l2cap/le/internal/link.h
+++ b/gd/l2cap/le/internal/link.h
@@ -37,7 +37,7 @@
Link(os::Handler* l2cap_handler, std::unique_ptr<hci::AclConnection> acl_connection,
l2cap::internal::ParameterProvider* parameter_provider)
: l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
- data_pipeline_manager_(l2cap_handler, acl_connection_->GetAclQueueEnd()),
+ data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()),
parameter_provider_(parameter_provider) {
ASSERT(l2cap_handler_ != nullptr);
ASSERT(acl_connection_ != nullptr);
diff --git a/gd/shim/l2cap.cc b/gd/shim/l2cap.cc
index 7af8f77..d703972 100644
--- a/gd/shim/l2cap.cc
+++ b/gd/shim/l2cap.cc
@@ -50,7 +50,8 @@
using ServiceInterfaceCallback =
std::function<void(l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result)>;
-using ConnectionInterfaceCallback = std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::DynamicChannel>)>;
+using ConnectionInterfaceCallback =
+ std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel>)>;
std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) {
packet::RawBuilder builder;
@@ -62,7 +63,7 @@
class ConnectionInterface {
public:
- ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::DynamicChannel> channel,
+ ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel,
os::Handler* handler)
: cid_(cid), channel_(std::move(channel)), handler_(handler), on_data_ready_callback_(nullptr),
on_connection_closed_callback_(nullptr), address_(channel_->GetDevice()) {
@@ -138,7 +139,7 @@
private:
const ConnectionInterfaceDescriptor cid_;
- const std::unique_ptr<l2cap::DynamicChannel> channel_;
+ const std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
os::Handler* handler_;
ReadDataReadyCallback on_data_ready_callback_;
@@ -154,7 +155,7 @@
struct ConnectionInterfaceManager {
public:
- ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::DynamicChannel> channel);
+ ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
void RemoveConnection(ConnectionInterfaceDescriptor cid);
void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
@@ -217,7 +218,8 @@
return current_connection_interface_descriptor_++;
}
-ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(std::unique_ptr<l2cap::DynamicChannel> channel) {
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
+ std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
if (!HasResources()) {
return kInvalidConnectionInterfaceDescriptor;
}
@@ -265,7 +267,7 @@
: connection_interface_manager_(connection_interface_manager), psm_(psm), address_(address),
on_open_(std::move(on_open)), completed_(std::move(completed)) {}
- void OnConnectionOpen(std::unique_ptr<l2cap::DynamicChannel> channel) {
+ void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
completed_.set_value(cid);
@@ -320,7 +322,7 @@
completed_.set_value();
}
- void OnConnectionOpen(std::unique_ptr<l2cap::DynamicChannel> channel) {
+ void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
psm_);
hci::Address address = channel->GetDevice();
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
index 7e14db6..4f0f132 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
@@ -18,4 +18,25 @@
using std::shared_ptr;
-namespace test_vendor_lib {} // namespace test_vendor_lib
+namespace test_vendor_lib {
+AclConnection::AclConnection(AddressWithType addr, AddressWithType own_addr,
+ Phy::Type phy_type)
+ : address_(addr), own_address_(own_addr), type_(phy_type) {}
+
+void AclConnection::Encrypt() { encrypted_ = true; };
+
+bool AclConnection::IsEncrypted() const { return encrypted_; };
+
+AddressWithType AclConnection::GetAddress() const { return address_; }
+
+void AclConnection::SetAddress(AddressWithType address) { address_ = address; }
+
+AddressWithType AclConnection::GetOwnAddress() const { return own_address_; }
+
+void AclConnection::SetOwnAddress(AddressWithType own_addr) {
+ own_address_ = own_addr;
+}
+
+Phy::Type AclConnection::GetPhyType() const { return type_; }
+
+} // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
index cc33c13..12e1779 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
@@ -18,50 +18,39 @@
#include <cstdint>
-#include "hci/address.h"
+#include "hci/address_with_type.h"
+#include "phy.h"
namespace test_vendor_lib {
-using ::bluetooth::hci::Address;
+using ::bluetooth::hci::AddressWithType;
// Model the connection of a device to the controller.
class AclConnection {
public:
- AclConnection(Address addr) : address_(addr), address_type_(0), own_address_type_(0) {}
+ AclConnection(AddressWithType addr, AddressWithType own_addr,
+ Phy::Type phy_type);
virtual ~AclConnection() = default;
- void Encrypt() {
- encrypted_ = true;
- };
- bool IsEncrypted() const {
- return encrypted_;
- };
+ void Encrypt();
- Address GetAddress() const {
- return address_;
- }
- void SetAddress(Address address) {
- address_ = address;
- }
+ bool IsEncrypted() const;
- uint8_t GetAddressType() const {
- return address_type_;
- }
- void SetAddressType(uint8_t address_type) {
- address_type_ = address_type;
- }
- uint8_t GetOwnAddressType() const {
- return own_address_type_;
- }
- void SetOwnAddressType(uint8_t address_type) {
- own_address_type_ = address_type;
- }
+ AddressWithType GetAddress() const;
+
+ void SetAddress(AddressWithType address);
+
+ AddressWithType GetOwnAddress() const;
+
+ void SetOwnAddress(AddressWithType own_addr);
+
+ Phy::Type GetPhyType() const;
private:
- Address address_;
- uint8_t address_type_;
- uint8_t own_address_type_;
+ AddressWithType address_;
+ AddressWithType own_address_;
+ Phy::Type type_{Phy::Type::BR_EDR};
// State variables
bool encrypted_{false};
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 014015a..d798e78 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
@@ -25,6 +25,8 @@
namespace test_vendor_lib {
using ::bluetooth::hci::Address;
+using ::bluetooth::hci::AddressType;
+using ::bluetooth::hci::AddressWithType;
bool AclConnectionHandler::HasHandle(uint16_t handle) const {
if (acl_connections_.count(handle) == 0) {
@@ -70,9 +72,16 @@
return true;
}
-bool AclConnectionHandler::CreatePendingLeConnection(Address addr, uint8_t address_type) {
- if (IsDeviceConnected(addr, address_type)) {
- LOG_INFO("%s: %s (type %hhx) is already connected", __func__, addr.ToString().c_str(), address_type);
+bool AclConnectionHandler::CreatePendingLeConnection(AddressWithType addr) {
+ bool device_connected = false;
+ for (auto pair : acl_connections_) {
+ auto connection = std::get<AclConnection>(pair);
+ if (connection.GetAddress() == addr) {
+ device_connected = true;
+ }
+ }
+ if (device_connected) {
+ LOG_INFO("%s: %s is already connected", __func__, addr.ToString().c_str());
return false;
}
if (le_connection_pending_) {
@@ -81,42 +90,44 @@
}
le_connection_pending_ = true;
pending_le_connection_address_ = addr;
- pending_le_connection_address_type_ = address_type;
return true;
}
-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;
+bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
+ return le_connection_pending_ && pending_le_connection_address_ == addr;
}
-bool AclConnectionHandler::CancelPendingLeConnection(Address addr, uint8_t address_type) {
- if (!le_connection_pending_ || pending_le_connection_address_ != addr ||
- pending_le_connection_address_type_ != address_type) {
+bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
+ if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
return false;
}
le_connection_pending_ = false;
- pending_le_connection_address_ = Address::kEmpty;
- pending_le_connection_address_type_ = 0xba;
+ pending_le_connection_address_ =
+ AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
return true;
}
-uint16_t AclConnectionHandler::CreateConnection(Address addr) {
+uint16_t AclConnectionHandler::CreateConnection(Address addr,
+ Address own_addr) {
if (CancelPendingConnection(addr)) {
uint16_t handle = GetUnusedHandle();
- acl_connections_.emplace(handle, addr);
+ acl_connections_.emplace(
+ handle,
+ AclConnection{
+ AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
+ AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
+ Phy::Type::BR_EDR});
return handle;
}
return acl::kReservedHandle;
}
-uint16_t AclConnectionHandler::CreateLeConnection(Address addr, uint8_t address_type, uint8_t own_address_type) {
- if (CancelPendingLeConnection(addr, address_type)) {
+uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
+ AddressWithType own_addr) {
+ if (CancelPendingLeConnection(addr)) {
uint16_t handle = GetUnusedHandle();
- acl_connections_.emplace(handle, addr);
- set_own_address_type(handle, own_address_type);
- SetAddress(handle, addr, address_type);
+ acl_connections_.emplace(
+ handle, AclConnection{addr, own_addr, Phy::Type::LOW_ENERGY});
return handle;
}
return acl::kReservedHandle;
@@ -126,7 +137,7 @@
return acl_connections_.erase(handle) > 0;
}
-uint16_t AclConnectionHandler::GetHandle(Address addr) const {
+uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
for (auto pair : acl_connections_) {
if (std::get<AclConnection>(pair).GetAddress() == addr) {
return std::get<0>(pair);
@@ -135,41 +146,24 @@
return acl::kReservedHandle;
}
-Address AclConnectionHandler::GetAddress(uint16_t handle) const {
+uint16_t AclConnectionHandler::GetHandleOnlyAddress(
+ bluetooth::hci::Address addr) const {
+ for (auto pair : acl_connections_) {
+ if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
+ return std::get<0>(pair);
+ }
+ }
+ return acl::kReservedHandle;
+}
+
+AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
return acl_connections_.at(handle).GetAddress();
}
-uint8_t AclConnectionHandler::GetAddressType(uint16_t handle) const {
+AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
- return acl_connections_.at(handle).GetAddressType();
-}
-
-void AclConnectionHandler::set_own_address_type(uint16_t handle, uint8_t address_type) {
- ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
- acl_connections_.at(handle).SetOwnAddressType(address_type);
-}
-
-uint8_t AclConnectionHandler::GetOwnAddressType(uint16_t handle) const {
- ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
- return acl_connections_.at(handle).GetOwnAddressType();
-}
-
-bool AclConnectionHandler::IsConnected(uint16_t handle) const {
- if (!HasHandle(handle)) {
- return false;
- }
- return true;
-}
-
-bool AclConnectionHandler::IsDeviceConnected(Address addr, uint8_t address_type) const {
- for (auto pair : acl_connections_) {
- auto connection = std::get<AclConnection>(pair);
- if (connection.GetAddress() == addr && connection.GetAddressType() == address_type) {
- return true;
- }
- }
- return false;
+ return acl_connections_.at(handle).GetOwnAddress();
}
void AclConnectionHandler::Encrypt(uint16_t handle) {
@@ -186,13 +180,20 @@
return acl_connections_.at(handle).IsEncrypted();
}
-void AclConnectionHandler::SetAddress(uint16_t handle, Address address, uint8_t address_type) {
+void AclConnectionHandler::SetAddress(uint16_t handle,
+ AddressWithType address) {
if (!HasHandle(handle)) {
return;
}
auto connection = acl_connections_.at(handle);
connection.SetAddress(address);
- connection.SetAddressType(address_type);
+}
+
+Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
+ if (!HasHandle(handle)) {
+ return Phy::Type::BR_EDR;
+ }
+ return acl_connections_.at(handle).GetPhyType();
}
} // namespace test_vendor_lib
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 c08f529..0f0b5a7 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
@@ -22,59 +22,60 @@
#include "acl_connection.h"
#include "hci/address.h"
+#include "hci/address_with_type.h"
#include "include/acl.h"
+#include "phy.h"
namespace test_vendor_lib {
-using ::bluetooth::hci::Address;
-
class AclConnectionHandler {
public:
AclConnectionHandler() = default;
virtual ~AclConnectionHandler() = default;
- bool CreatePendingConnection(Address addr, bool authenticate_on_connect);
- bool HasPendingConnection(Address addr) const;
- bool CancelPendingConnection(Address addr);
+ bool CreatePendingConnection(bluetooth::hci::Address addr,
+ bool authenticate_on_connect);
+ bool HasPendingConnection(bluetooth::hci::Address addr) const;
+ bool CancelPendingConnection(bluetooth::hci::Address addr);
bool AuthenticatePendingConnection() const;
- bool CreatePendingLeConnection(Address addr, uint8_t addr_type);
- bool HasPendingLeConnection(Address addr, uint8_t addr_type) const;
- bool CancelPendingLeConnection(Address addr, uint8_t addr_type);
+ bool CreatePendingLeConnection(bluetooth::hci::AddressWithType addr);
+ bool HasPendingLeConnection(bluetooth::hci::AddressWithType addr) const;
+ bool CancelPendingLeConnection(bluetooth::hci::AddressWithType addr);
- uint16_t CreateConnection(Address addr);
- uint16_t CreateLeConnection(Address addr, uint8_t address_type, uint8_t own_address_type);
+ uint16_t CreateConnection(bluetooth::hci::Address addr,
+ bluetooth::hci::Address own_addr);
+ uint16_t CreateLeConnection(bluetooth::hci::AddressWithType addr,
+ bluetooth::hci::AddressWithType own_addr);
bool Disconnect(uint16_t handle);
bool HasHandle(uint16_t handle) const;
- uint16_t GetHandle(Address addr) const;
- Address GetAddress(uint16_t handle) const;
- uint8_t GetAddressType(uint16_t handle) const;
- uint8_t GetOwnAddressType(uint16_t handle) const;
-
- void SetConnected(uint16_t handle, bool connected);
- bool IsConnected(uint16_t handle) const;
-
- bool IsDeviceConnected(Address addr, uint8_t address_type = 0) const;
+ uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const;
+ uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const;
+ bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const;
+ bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const;
void Encrypt(uint16_t handle);
bool IsEncrypted(uint16_t handle) const;
- void SetAddress(uint16_t handle, Address address, uint8_t address_type = 0); // default to public
+ void SetAddress(uint16_t handle, bluetooth::hci::AddressWithType address);
+
+ Phy::Type GetPhyType(uint16_t handle) const;
private:
std::unordered_map<uint16_t, AclConnection> acl_connections_;
bool classic_connection_pending_{false};
- Address pending_connection_address_{Address::kEmpty};
+ bluetooth::hci::Address pending_connection_address_{
+ bluetooth::hci::Address::kEmpty};
bool authenticate_pending_classic_connection_{false};
bool le_connection_pending_{false};
- Address pending_le_connection_address_{Address::kEmpty};
- uint8_t pending_le_connection_address_type_{false};
+ bluetooth::hci::AddressWithType pending_le_connection_address_{
+ bluetooth::hci::Address::kEmpty,
+ bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS};
uint16_t GetUnusedHandle();
uint16_t last_handle_{acl::kReservedHandle - 2};
- void set_own_address_type(uint16_t handle, uint8_t own_address_type);
};
} // namespace test_vendor_lib
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 8f0975d..2c78ffb 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
@@ -104,8 +104,8 @@
if (!connections_.HasHandle(handle)) {
return ErrorCode::UNKNOWN_CONNECTION;
}
- return SendCommandToRemoteByAddress(opcode, args,
- connections_.GetAddress(handle));
+ return SendCommandToRemoteByAddress(
+ opcode, args, connections_.GetAddress(handle).GetAddress());
}
ErrorCode LinkLayerController::SendAclToRemote(
@@ -115,11 +115,9 @@
return ErrorCode::UNKNOWN_CONNECTION;
}
- Address my_address = properties_.GetAddress();
- Address destination = connections_.GetAddress(handle);
- if (connections_.GetOwnAddressType(handle) != 0) { // If it's not public, it must be LE
- my_address = properties_.GetLeAddress();
- }
+ AddressWithType my_address = connections_.GetOwnAddress(handle);
+ AddressWithType destination = connections_.GetAddress(handle);
+ Phy::Type phy = connections_.GetPhyType(handle);
LOG_INFO("%s(%s): handle 0x%x size %d", __func__, properties_.GetAddress().ToString().c_str(), handle,
static_cast<int>(acl_packet.size()));
@@ -150,9 +148,17 @@
raw_builder_ptr->AddOctets(payload_bytes);
auto acl = model::packets::AclPacketBuilder::Create(
- my_address, destination, std::move(raw_builder_ptr));
+ my_address.GetAddress(), destination.GetAddress(),
+ std::move(raw_builder_ptr));
- SendLinkLayerPacket(std::move(acl));
+ switch (phy) {
+ case Phy::Type::BR_EDR:
+ SendLinkLayerPacket(std::move(acl));
+ break;
+ case Phy::Type::LOW_ENERGY:
+ SendLeLinkLayerPacket(std::move(acl));
+ break;
+ }
return ErrorCode::SUCCESS;
}
@@ -287,15 +293,16 @@
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: remote handle 0x%x size %d", __func__, acl_view.GetHandle(),
+ static_cast<int>(acl_view.size()));
+ uint16_t local_handle =
+ connections_.GetHandleOnlyAddress(incoming.GetSourceAddress());
LOG_INFO("%s: local handle 0x%x", __func__, local_handle);
- 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);
+ std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
+ std::make_unique<bluetooth::packet::RawBuilder>(payload_data);
auto acl_packet = bluetooth::hci::AclPacketBuilder::Create(
local_handle, acl_view.GetPacketBoundaryFlag(),
@@ -354,15 +361,15 @@
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(
- ErrorCode::SUCCESS, handle, view.GetFeatures()));
- } else {
+ uint16_t handle = connections_.GetHandleOnlyAddress(source);
+ if (handle == acl::kReservedHandle) {
LOG_INFO("Discarding response from a disconnected device %s",
source.ToString().c_str());
+ return;
}
+ send_event_(
+ bluetooth::hci::ReadRemoteSupportedFeaturesCompleteBuilder::Create(
+ ErrorCode::SUCCESS, handle, view.GetFeatures()));
}
void LinkLayerController::IncomingReadRemoteExtendedFeatures(
@@ -387,16 +394,16 @@
model::packets::ReadRemoteExtendedFeaturesResponseView::Create(packet);
ASSERT(view.IsValid());
Address source = packet.GetSourceAddress();
- if (connections_.IsDeviceConnected(source)) {
- uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+ uint16_t handle = connections_.GetHandleOnlyAddress(source);
+ if (handle == acl::kReservedHandle) {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
+ return;
+ }
send_event_(
bluetooth::hci::ReadRemoteExtendedFeaturesCompleteBuilder::Create(
static_cast<ErrorCode>(view.GetStatus()), handle,
view.GetPageNumber(), view.GetMaxPageNumber(), view.GetFeatures()));
- } else {
- LOG_INFO("Discarding response from a disconnected device %s",
- source.ToString().c_str());
- }
}
void LinkLayerController::IncomingReadRemoteVersion(
@@ -413,16 +420,16 @@
model::packets::ReadRemoteVersionInformationResponseView::Create(packet);
ASSERT(view.IsValid());
Address source = packet.GetSourceAddress();
- if (connections_.IsDeviceConnected(source)) {
- uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+ uint16_t handle = connections_.GetHandleOnlyAddress(source);
+ if (handle == acl::kReservedHandle) {
+ LOG_INFO("Discarding response from a disconnected device %s",
+ source.ToString().c_str());
+ return;
+ }
send_event_(
bluetooth::hci::ReadRemoteVersionInformationCompleteBuilder::Create(
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(
@@ -437,14 +444,14 @@
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(
- ErrorCode::SUCCESS, handle, view.GetOffset()));
- } else {
+ uint16_t handle = connections_.GetHandleOnlyAddress(source);
+ if (handle == acl::kReservedHandle) {
LOG_INFO("Discarding response from a disconnected device %s",
source.ToString().c_str());
+ return;
}
+ send_event_(bluetooth::hci::ReadClockOffsetCompleteBuilder::Create(
+ ErrorCode::SUCCESS, handle, view.GetOffset()));
}
void LinkLayerController::IncomingDisconnectPacket(
@@ -454,9 +461,10 @@
ASSERT(disconnect.IsValid());
Address peer = incoming.GetSourceAddress();
- uint16_t handle = connections_.GetHandle(peer);
+ uint16_t handle = connections_.GetHandleOnlyAddress(peer);
if (handle == acl::kReservedHandle) {
- LOG_INFO("%s: Unknown connection @%s", __func__, peer.ToString().c_str());
+ LOG_INFO("Discarding disconnect from a disconnected device %s",
+ peer.ToString().c_str());
return;
}
ASSERT_LOG(connections_.Disconnect(handle), "GetHandle() returned invalid handle %hx", handle);
@@ -471,7 +479,7 @@
// TODO: Check keys
Address peer = incoming.GetSourceAddress();
- uint16_t handle = connections_.GetHandle(peer);
+ uint16_t handle = connections_.GetHandleOnlyAddress(peer);
if (handle == acl::kReservedHandle) {
LOG_INFO("%s: Unknown connection @%s", __func__, peer.ToString().c_str());
return;
@@ -495,7 +503,8 @@
model::packets::LinkLayerPacketView incoming) {
LOG_INFO("%s", __func__);
// TODO: Check keys
- uint16_t handle = connections_.GetHandle(incoming.GetSourceAddress());
+ uint16_t handle =
+ connections_.GetHandleOnlyAddress(incoming.GetSourceAddress());
if (handle == acl::kReservedHandle) {
LOG_INFO("%s: Unknown connection @%s", __func__, incoming.GetSourceAddress().ToString().c_str());
return;
@@ -636,7 +645,8 @@
uint8_t oob_data_present = request.GetOobDataPresent();
uint8_t authentication_requirements = request.GetAuthenticationRequirements();
- uint16_t handle = connections_.GetHandle(peer);
+ uint16_t handle = connections_.GetHandle(AddressWithType(
+ peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS));
if (handle == acl::kReservedHandle) {
LOG_INFO("%s: Device not connected %s", __func__, peer.ToString().c_str());
return;
@@ -707,8 +717,7 @@
ASSERT(advertisement.IsValid());
auto adv_type = static_cast<LeAdvertisement::AdvertisementType>(
advertisement.GetAdvertisementType());
- auto address_type =
- static_cast<LeAdvertisement::AddressType>(advertisement.GetAddressType());
+ auto address_type = advertisement.GetAddressType();
if (le_scan_enable_) {
vector<uint8_t> ad = advertisement.GetData();
@@ -737,13 +746,19 @@
}
// Connect
- if ((le_connect_ && le_peer_address_ == address && le_peer_address_type_ == static_cast<uint8_t>(address_type) &&
+ if ((le_connect_ && le_peer_address_ == address &&
+ le_peer_address_type_ == static_cast<uint8_t>(address_type) &&
(adv_type == LeAdvertisement::AdvertisementType::ADV_IND ||
adv_type == LeAdvertisement::AdvertisementType::ADV_DIRECT_IND)) ||
- (LeWhiteListContainsDevice(address, static_cast<uint8_t>(address_type)))) {
- if (!connections_.CreatePendingLeConnection(incoming.GetSourceAddress(), static_cast<uint8_t>(address_type))) {
- LOG_WARN("%s: CreatePendingLeConnection failed for connection to %s (type %hhx)", __func__,
- incoming.GetSourceAddress().ToString().c_str(), address_type);
+ (LeWhiteListContainsDevice(address,
+ static_cast<uint8_t>(address_type)))) {
+ if (!connections_.CreatePendingLeConnection(AddressWithType(
+ address, static_cast<bluetooth::hci::AddressType>(address_type)))) {
+ LOG_WARN(
+ "%s: CreatePendingLeConnection failed for connection to %s (type "
+ "%hhx)",
+ __func__, incoming.GetSourceAddress().ToString().c_str(),
+ address_type);
}
LOG_INFO("%s: connecting to %s (type %hhx)", __func__, incoming.GetSourceAddress().ToString().c_str(),
address_type);
@@ -760,20 +775,23 @@
}
}
-void LinkLayerController::HandleLeConnection(Address address, uint8_t address_type, uint8_t own_address_type,
- uint8_t role, uint16_t connection_interval, uint16_t connection_latency,
+void LinkLayerController::HandleLeConnection(AddressWithType address,
+ AddressWithType own_address,
+ uint8_t role,
+ uint16_t connection_interval,
+ uint16_t connection_latency,
uint16_t supervision_timeout) {
// TODO: Choose between LeConnectionComplete and LeEnhancedConnectionComplete
- uint16_t handle = connections_.CreateLeConnection(address, address_type, own_address_type);
+ uint16_t handle = connections_.CreateLeConnection(address, own_address);
if (handle == acl::kReservedHandle) {
- LOG_WARN("%s: No pending connection for connection from %s (type %hhx)", __func__, address.ToString().c_str(),
- address_type);
+ LOG_WARN("%s: No pending connection for connection from %s", __func__,
+ address.ToString().c_str());
return;
}
auto packet = bluetooth::hci::LeConnectionCompleteBuilder::Create(
ErrorCode::SUCCESS, handle, static_cast<bluetooth::hci::Role>(role),
- static_cast<bluetooth::hci::AddressType>(address_type), address,
- connection_interval, connection_latency, supervision_timeout,
+ address.GetAddressType(), address.GetAddress(), connection_interval,
+ connection_latency, supervision_timeout,
static_cast<bluetooth::hci::MasterClockAccuracy>(0x00));
send_event_(std::move(packet));
}
@@ -782,17 +800,26 @@
model::packets::LinkLayerPacketView incoming) {
auto connect = model::packets::LeConnectView::Create(incoming);
ASSERT(connect.IsValid());
- uint16_t connection_interval = (connect.GetLeConnectionIntervalMax() + connect.GetLeConnectionIntervalMin()) / 2;
- if (!connections_.CreatePendingLeConnection(incoming.GetSourceAddress(),
- static_cast<uint8_t>(connect.GetAddressType()))) {
- LOG_WARN("%s: CreatePendingLeConnection failed for connection from %s (type %hhx)", __func__,
- incoming.GetSourceAddress().ToString().c_str(), connect.GetAddressType());
+ uint16_t connection_interval = (connect.GetLeConnectionIntervalMax() +
+ connect.GetLeConnectionIntervalMin()) /
+ 2;
+ if (!connections_.CreatePendingLeConnection(AddressWithType(
+ incoming.GetSourceAddress(), static_cast<bluetooth::hci::AddressType>(
+ connect.GetAddressType())))) {
+ LOG_WARN(
+ "%s: CreatePendingLeConnection failed for connection from %s (type "
+ "%hhx)",
+ __func__, incoming.GetSourceAddress().ToString().c_str(),
+ connect.GetAddressType());
return;
}
HandleLeConnection(
- incoming.GetSourceAddress(),
- static_cast<uint8_t>(connect.GetAddressType()),
- static_cast<uint8_t>(properties_.GetLeAdvertisingOwnAddressType()),
+ AddressWithType(
+ incoming.GetSourceAddress(),
+ static_cast<bluetooth::hci::AddressType>(connect.GetAddressType())),
+ AddressWithType(incoming.GetDestinationAddress(),
+ static_cast<bluetooth::hci::AddressType>(
+ properties_.GetLeAdvertisingOwnAddressType())),
static_cast<uint8_t>(bluetooth::hci::Role::SLAVE), connection_interval,
connect.GetLeConnectionLatency(),
connect.GetLeConnectionSupervisionTimeout());
@@ -809,13 +836,16 @@
model::packets::LinkLayerPacketView incoming) {
auto complete = model::packets::LeConnectCompleteView::Create(incoming);
ASSERT(complete.IsValid());
- HandleLeConnection(incoming.GetSourceAddress(),
- static_cast<uint8_t>(complete.GetAddressType()),
- static_cast<uint8_t>(le_address_type_),
- static_cast<uint8_t>(bluetooth::hci::Role::MASTER),
- complete.GetLeConnectionInterval(),
- complete.GetLeConnectionLatency(),
- complete.GetLeConnectionSupervisionTimeout());
+ HandleLeConnection(
+ AddressWithType(
+ incoming.GetSourceAddress(),
+ static_cast<bluetooth::hci::AddressType>(complete.GetAddressType())),
+ AddressWithType(
+ incoming.GetDestinationAddress(),
+ static_cast<bluetooth::hci::AddressType>(le_address_type_)),
+ static_cast<uint8_t>(bluetooth::hci::Role::MASTER),
+ complete.GetLeConnectionInterval(), complete.GetLeConnectionLatency(),
+ complete.GetLeConnectionSupervisionTimeout());
}
void LinkLayerController::IncomingLeScanPacket(
@@ -900,7 +930,8 @@
Address peer = incoming.GetSourceAddress();
LOG_INFO("%s: %s", __func__, peer.ToString().c_str());
bool awaiting_authentication = connections_.AuthenticatePendingConnection();
- uint16_t handle = connections_.CreateConnection(peer);
+ uint16_t handle =
+ connections_.CreateConnection(peer, incoming.GetDestinationAddress());
if (handle == acl::kReservedHandle) {
LOG_WARN("%s: No free handles", __func__);
return;
@@ -1084,7 +1115,7 @@
const Address& address) {
security_manager_.DeleteKey(address);
// Simple pairing to get a key
- uint16_t handle = connections_.GetHandle(address);
+ uint16_t handle = connections_.GetHandleOnlyAddress(address);
if (handle == acl::kReservedHandle) {
LOG_INFO("%s: Device not connected %s", __func__, address.ToString().c_str());
return ErrorCode::UNKNOWN_CONNECTION;
@@ -1220,9 +1251,11 @@
return ErrorCode::UNKNOWN_CONNECTION;
}
- Address remote = connections_.GetAddress(handle);
+ AddressWithType remote = connections_.GetAddress(handle);
- ScheduleTask(milliseconds(5), [this, remote, handle]() { HandleAuthenticationRequest(remote, handle); });
+ ScheduleTask(milliseconds(5), [this, remote, handle]() {
+ HandleAuthenticationRequest(remote.GetAddress(), handle);
+ });
return ErrorCode::SUCCESS;
}
@@ -1261,14 +1294,15 @@
if (connections_.IsEncrypted(handle) && !encryption_enable) {
return ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE;
}
- Address remote = connections_.GetAddress(handle);
+ AddressWithType remote = connections_.GetAddress(handle);
- if (security_manager_.ReadKey(remote) == 0) {
+ if (security_manager_.ReadKey(remote.GetAddress()) == 0) {
return ErrorCode::PIN_OR_KEY_MISSING;
}
ScheduleTask(milliseconds(5), [this, remote, handle, encryption_enable]() {
- HandleSetConnectionEncryption(remote, handle, encryption_enable);
+ HandleSetConnectionEncryption(remote.GetAddress(), handle,
+ encryption_enable);
});
return ErrorCode::SUCCESS;
}
@@ -1295,7 +1329,8 @@
properties_.GetAddress(), addr, try_role_switch);
SendLinkLayerPacket(std::move(to_send));
- uint16_t handle = connections_.CreateConnection(addr);
+ uint16_t handle =
+ connections_.CreateConnection(addr, properties_.GetAddress());
if (handle == acl::kReservedHandle) {
LOG_INFO("%s CreateConnection failed", __func__);
return;
@@ -1356,14 +1391,13 @@
}
ErrorCode LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) {
- // TODO: Handle LE
if (!connections_.HasHandle(handle)) {
return ErrorCode::UNKNOWN_CONNECTION;
}
- const Address& remote = connections_.GetAddress(handle);
+ const AddressWithType remote = connections_.GetAddress(handle);
auto packet = model::packets::DisconnectBuilder::Create(
- properties_.GetAddress(), remote, reason);
+ properties_.GetAddress(), remote.GetAddress(), reason);
SendLinkLayerPacket(std::move(packet));
ASSERT_LOG(connections_.Disconnect(handle), "Disconnecting %hx", handle);
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 b287123..79027ec 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
@@ -131,8 +131,10 @@
void LeAdvertising();
- void HandleLeConnection(Address addr, uint8_t addr_type, uint8_t own_addr_type, uint8_t role,
- uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout);
+ void HandleLeConnection(AddressWithType addr, AddressWithType own_addr,
+ uint8_t role, uint16_t connection_interval,
+ uint16_t connection_latency,
+ uint16_t supervision_timeout);
void LeWhiteListClear();
void LeWhiteListAddDevice(Address addr, uint8_t addr_type);