summaryrefslogtreecommitdiff
path: root/system/gd/l2cap/le/internal/link.h
blob: 17d69053252c6f1d945f163b75c8b1a838e5d365 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * 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 <atomic>
#include <chrono>
#include <memory>

#include "hci/acl_manager/le_acl_connection.h"
#include "l2cap/internal/data_pipeline_manager.h"
#include "l2cap/internal/dynamic_channel_allocator.h"
#include "l2cap/internal/fixed_channel_allocator.h"
#include "l2cap/internal/ilink.h"
#include "l2cap/internal/parameter_provider.h"
#include "l2cap/le/dynamic_channel_manager.h"
#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h"
#include "l2cap/le/internal/fixed_channel_impl.h"
#include "l2cap/le/internal/fixed_channel_service_manager_impl.h"
#include "l2cap/le/internal/signalling_manager.h"
#include "l2cap/le/link_options.h"
#include "l2cap/le/security_enforcement_interface.h"
#include "os/alarm.h"

namespace bluetooth {
namespace l2cap {
namespace le {
namespace internal {

class LinkManager;

class Link : public l2cap::internal::ILink, public hci::acl_manager::LeConnectionManagementCallbacks {
 public:
  Link(os::Handler* l2cap_handler, std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection,
       l2cap::internal::ParameterProvider* parameter_provider,
       DynamicChannelServiceManagerImpl* dynamic_service_manager, FixedChannelServiceManagerImpl* fixed_service_manager,
       LinkManager* link_manager);

  Link(const Link&) = delete;
  Link& operator=(const Link&) = delete;

  ~Link() = default;

  inline hci::AddressWithType GetDevice() const override {
    return acl_connection_->GetRemoteAddress();
  }

  struct PendingDynamicChannelConnection {
    os::Handler* handler_;
    DynamicChannelManager::OnConnectionOpenCallback on_open_callback_;
    DynamicChannelManager::OnConnectionFailureCallback on_fail_callback_;
    le::DynamicChannelConfigurationOption configuration_;
  };

  inline virtual hci::Role GetRole() {
    return acl_connection_->GetRole();
  }

  inline virtual hci::acl_manager::LeAclConnection* GetAclConnection() {
    return acl_connection_.get();
  }

  // ACL methods

  virtual void OnAclDisconnected(hci::ErrorCode reason);

  void OnDisconnection(hci::ErrorCode reason) override;

  void OnConnectionUpdate(
      hci::ErrorCode hci_status,
      uint16_t connection_interval,
      uint16_t connection_latency,
      uint16_t supervision_timeout) override;

  void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override;

  void OnReadRemoteVersionInformationComplete(
      hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) override;

  void OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status, uint64_t features) override;

  void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override;

  void OnLocalAddressUpdate(hci::AddressWithType address_with_type) override;

  virtual void Disconnect();

  // Handles connection parameter update request from remote
  virtual void UpdateConnectionParameterFromRemote(SignalId signal_id, uint16_t conn_interval_min,
                                                   uint16_t conn_interval_max, uint16_t conn_latency,
                                                   uint16_t supervision_timeout);
  virtual bool CheckConnectionParameters(
      uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout);

  virtual void SendConnectionParameterUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max,
                                             uint16_t conn_latency, uint16_t supervision_timeout,
                                             uint16_t min_ce_length, uint16_t max_ce_length);

  // FixedChannel methods

  virtual std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid, SecurityPolicy security_policy);

  virtual bool IsFixedChannelAllocated(Cid cid);

  // DynamicChannel methods

  virtual Cid ReserveDynamicChannel();

  virtual void SendConnectionRequest(Psm psm, PendingDynamicChannelConnection pending_dynamic_channel_connection);

  void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) override;

  // Invoked by signalling manager to indicate an outgoing connection request failed and link shall free resources
  virtual void OnOutgoingConnectionRequestFail(Cid local_cid, LeCreditBasedConnectionResponseResult result);

  virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateDynamicChannel(Psm psm, Cid remote_cid);

  virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateReservedDynamicChannel(Cid reserved_cid, Psm psm,
                                                                                              Cid remote_cid);

  virtual void FreeDynamicChannel(Cid cid);

  // Check how many channels are acquired or in use, if zero, start tear down timer, if non-zero, cancel tear down timer
  virtual void RefreshRefCount();

  void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel);
  void NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result);

  virtual std::string ToString() {
    return GetDevice().ToString();
  }

  virtual uint16_t GetMps() const;

  virtual uint16_t GetInitialCredit() const;

  void SendLeCredit(Cid local_cid, uint16_t credit) override;

  LinkOptions* GetLinkOptions() {
    return &link_options_;
  }

  void ReadRemoteVersionInformation();

  void OnPendingPacketChange(Cid local_cid, bool has_packet) override;

 private:
  os::Handler* l2cap_handler_;
  l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
  l2cap::internal::DynamicChannelAllocator dynamic_channel_allocator_{this, l2cap_handler_};
  std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection_;
  l2cap::internal::DataPipelineManager data_pipeline_manager_;
  l2cap::internal::ParameterProvider* parameter_provider_;
  DynamicChannelServiceManagerImpl* dynamic_service_manager_;
  LeSignallingManager signalling_manager_;
  std::unordered_map<Cid, PendingDynamicChannelConnection> local_cid_to_pending_dynamic_channel_connection_map_;
  os::Alarm link_idle_disconnect_alarm_{l2cap_handler_};
  LinkOptions link_options_{acl_connection_.get(), this, l2cap_handler_};
  LinkManager* link_manager_;
  SignalId update_request_signal_id_ = kInvalidSignalId;
  uint16_t update_request_interval_min_;
  uint16_t update_request_interval_max_;
  uint16_t update_request_latency_;
  uint16_t update_request_supervision_timeout_;
  std::atomic_int remaining_packets_to_be_sent_ = 0;

  // Received connection update complete from ACL manager. SignalId is bound to a valid number when we need to send a
  // response to remote. If SignalId is bound to an invalid number, we don't send a response to remote, because the
  // connection update request is not from remote LL peripheral.
  void on_connection_update_complete(SignalId signal_id, hci::ErrorCode error_code);
};

}  // namespace internal
}  // namespace le
}  // namespace l2cap
}  // namespace bluetooth