| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef GARNET_DRIVERS_BLUETOOTH_LIB_DATA_FAKE_DOMAIN_H_ |
| #define GARNET_DRIVERS_BLUETOOTH_LIB_DATA_FAKE_DOMAIN_H_ |
| |
| #include "garnet/drivers/bluetooth/lib/data/domain.h" |
| #include "garnet/drivers/bluetooth/lib/data/l2cap_socket_factory.h" |
| |
| namespace btlib { |
| |
| namespace l2cap { |
| namespace testing { |
| class FakeChannel; |
| } // namespace testing |
| } // namespace l2cap |
| |
| namespace data { |
| namespace testing { |
| |
| // This is a fake version of the Domain class that can be injected into other |
| // layers for unit testing. |
| class FakeDomain final : public Domain { |
| public: |
| inline static fbl::RefPtr<FakeDomain> Create() { |
| return fbl::AdoptRef(new FakeDomain()); |
| } |
| |
| // Triggers a LE connection parameter update callback on the given link. |
| void TriggerLEConnectionParameterUpdate( |
| hci::ConnectionHandle handle, |
| const hci::LEPreferredConnectionParameters& params); |
| |
| // Triggers the completed opening of an outbound dynamic channel on the given |
| // link. The channels created will be provided to callers of OpenChannel, |
| // where multiple requests for the same PSM will be handled in FIFO order. |
| void TriggerOutboundL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm, |
| l2cap::ChannelId id, |
| l2cap::ChannelId remote_id); |
| |
| // Triggers the creation of an inbound dynamic channel on the given link. The |
| // channels created will be provided to handlers passed to RegisterService. |
| void TriggerInboundL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm, |
| l2cap::ChannelId id, |
| l2cap::ChannelId remote_id); |
| |
| // Triggers a link error callback on the given link. |
| void TriggerLinkError(hci::ConnectionHandle handle); |
| |
| // Domain overrides: |
| void Initialize() override; |
| void ShutDown() override; |
| void AddACLConnection(hci::ConnectionHandle handle, |
| hci::Connection::Role role, |
| l2cap::LinkErrorCallback link_error_callback, |
| async_dispatcher_t* dispatcher) override; |
| void AddLEConnection( |
| hci::ConnectionHandle handle, hci::Connection::Role role, |
| l2cap::LinkErrorCallback link_error_callback, |
| l2cap::LEFixedChannelsCallback channel_callback, |
| l2cap::LEConnectionParameterUpdateCallback conn_param_callback, |
| async_dispatcher_t* dispatcher) override; |
| void RemoveConnection(hci::ConnectionHandle handle) override; |
| void OpenL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm, |
| l2cap::ChannelCallback cb, |
| async_dispatcher_t* dispatcher) override; |
| void OpenL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm, |
| SocketCallback socket_callback, |
| async_dispatcher_t* dispatcher) override; |
| void RegisterService(l2cap::PSM psm, l2cap::ChannelCallback channel_callback, |
| async_dispatcher_t* dispatcher) override; |
| void RegisterService(l2cap::PSM psm, SocketCallback socket_callback, |
| async_dispatcher_t* dispatcher) override; |
| void UnregisterService(l2cap::PSM psm) override; |
| |
| // Called when a new channel gets opened. Tests can use this to obtain a |
| // reference to all channels. |
| using FakeChannelCallback = |
| fit::function<void(fbl::RefPtr<l2cap::testing::FakeChannel>)>; |
| void set_channel_callback(FakeChannelCallback callback) { |
| chan_cb_ = std::move(callback); |
| } |
| |
| private: |
| friend class fbl::RefPtr<FakeDomain>; |
| |
| // TODO(armansito): Consider moving the following logic into an internal fake |
| // that is L2CAP-specific. |
| using ChannelDelivery = |
| std::pair<l2cap::ChannelCallback, async_dispatcher_t*>; |
| struct LinkData { |
| hci::ConnectionHandle handle; |
| hci::Connection::Role role; |
| hci::Connection::LinkType type; |
| |
| async_dispatcher_t* dispatcher; |
| |
| // Dual-mode callbacks |
| l2cap::LinkErrorCallback link_error_cb; |
| std::unordered_map<l2cap::PSM, std::list<ChannelDelivery>> |
| outbound_conn_cbs; |
| |
| // LE-only callbacks |
| l2cap::LEConnectionParameterUpdateCallback le_conn_param_cb; |
| }; |
| |
| FakeDomain() = default; |
| ~FakeDomain() override = default; |
| |
| LinkData* RegisterInternal(hci::ConnectionHandle handle, |
| hci::Connection::Role role, |
| hci::Connection::LinkType link_type, |
| l2cap::LinkErrorCallback link_error_callback, |
| async_dispatcher_t* dispatcher); |
| fbl::RefPtr<l2cap::testing::FakeChannel> OpenFakeChannel( |
| LinkData* link, l2cap::ChannelId id, l2cap::ChannelId remote_id); |
| fbl::RefPtr<l2cap::testing::FakeChannel> OpenFakeFixedChannel( |
| LinkData* link, l2cap::ChannelId id); |
| LinkData& FindLinkData(hci::ConnectionHandle handle); |
| |
| bool initialized_ = false; |
| std::unordered_map<hci::ConnectionHandle, LinkData> links_; |
| FakeChannelCallback chan_cb_; |
| std::unordered_map<l2cap::PSM, ChannelDelivery> inbound_conn_cbs_; |
| |
| // Makes sockets for RegisterService |
| internal::L2capSocketFactory socket_factory_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(FakeDomain); |
| }; |
| |
| } // namespace testing |
| } // namespace data |
| } // namespace btlib |
| |
| #endif // GARNET_DRIVERS_BLUETOOTH_LIB_DATA_FAKE_DOMAIN_H_ |