1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <string>
19 
20 #include "hci/acl_manager.h"
21 #include "hci/address.h"
22 #include "l2cap/l2cap_packets.h"
23 #include "l2cap/le/dynamic_channel.h"
24 #include "l2cap/le/dynamic_channel_configuration_option.h"
25 #include "l2cap/le/dynamic_channel_service.h"
26 #include "l2cap/le/security_policy.h"
27 #include "l2cap/psm.h"
28 #include "os/handler.h"
29 
30 namespace bluetooth {
31 namespace l2cap {
32 namespace le {
33 
34 class L2capLeModule;
35 
36 namespace internal {
37 class LinkManager;
38 class DynamicChannelServiceManagerImpl;
39 }  // namespace internal
40 
41 class DynamicChannelManager {
42  public:
43   enum class ConnectionResultCode {
44     SUCCESS = 0,
45     FAIL_NO_SERVICE_REGISTERED = 1,  // No service is registered
46     FAIL_HCI_ERROR = 2,              // See hci_error
47     FAIL_L2CAP_ERROR = 3,            // See l2cap_connection_response_result
48   };
49 
50   struct ConnectionResult {
51     ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS;
52     hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS;
53     LeCreditBasedConnectionResponseResult l2cap_connection_response_result =
54         LeCreditBasedConnectionResponseResult::SUCCESS;
55   };
56   /**
57    * OnConnectionFailureCallback(std::string failure_reason);
58    */
59   using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult result)>;
60 
61   /**
62    * OnConnectionOpenCallback(DynamicChannel channel);
63    */
64   using OnConnectionOpenCallback = common::Callback<void(std::unique_ptr<DynamicChannel>)>;
65 
66   enum class RegistrationResult {
67     SUCCESS = 0,
68     FAIL_DUPLICATE_SERVICE = 1,  // Duplicate service registration for the same PSM
69     FAIL_INVALID_SERVICE = 2,    // Invalid PSM
70   };
71 
72   /**
73    * OnRegistrationFailureCallback(RegistrationResult result, DynamicChannelService service);
74    */
75   using OnRegistrationCompleteCallback =
76       common::OnceCallback<void(RegistrationResult, std::unique_ptr<DynamicChannelService>)>;
77 
78   /**
79    * Connect to a Dynamic channel on a remote device
80    *
81    * - This method is asynchronous
82    * - When false is returned, the connection fails immediately
83    * - When true is returned, method caller should wait for on_fail_callback or on_open_callback
84    * - If an LE connection does not exist, this method will create an LE connection
85    * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR
86    * - If Dynamic channel on a remote device is already reported as connected via on_open_callback, it won't be
87    *   reported again
88    *
89    * @param device: Remote device to make this connection.
90    * @param psm: Service PSM to connect. PSM is defined in Core spec Vol 3 Part A 4.2.
91    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
92    * @param on_fail_callback: A callback to indicate connection failure along with a status code.
93    * @param handler: The handler context in which to execute the @callback parameters.
94    * @param configuration_option: The configuration options for this channel
95    *
96    * Returns: true if connection was able to be initiated, false otherwise.
97    */
98   bool ConnectChannel(hci::AddressWithType device, DynamicChannelConfigurationOption configuration_option, Psm psm,
99                       OnConnectionOpenCallback on_connection_open, OnConnectionFailureCallback on_fail_callback,
100                       os::Handler* handler);
101 
102   /**
103    * Register a service to receive incoming connections bound to a specific channel.
104    *
105    * - This method is asynchronous.
106    * - When false is returned, the registration fails immediately.
107    * - When true is returned, method caller should wait for on_service_registered callback that contains a
108    *   DynamicChannelService object. The registered service can be managed from that object.
109    * - If a PSM is already registered or some other error happens, on_registration_complete will be triggered with a
110    *   non-SUCCESS value
111    * - After a service is registered, a DynamicChannel is delivered through on_open_callback when the remote
112    *   initiates a channel open and channel is opened successfully
113    * - on_open_callback, will only be triggered after on_service_registered callback
114    *
115    * @param security_policy: The security policy used for the connection.
116    * @param psm: Service PSM to register. PSM is defined in Core spec Vol 3 Part A 4.2.
117    * @param on_registration_complete: A callback to indicate the service setup has completed. If the return status is
118    *        not SUCCESS, it means service is not registered due to reasons like PSM already take
119    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
120    * @param handler: The handler context in which to execute the @callback parameter.
121    * @param configuration_option: The configuration options for this channel
122    */
123   bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
124                        const SecurityPolicy& security_policy, OnRegistrationCompleteCallback on_registration_complete,
125                        OnConnectionOpenCallback on_connection_open, os::Handler* handler);
126 
127   friend class L2capLeModule;
128 
129  private:
130   // The constructor is not to be used by user code
DynamicChannelManager(internal::DynamicChannelServiceManagerImpl * service_manager,internal::LinkManager * link_manager,os::Handler * l2cap_layer_handler)131   DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager,
132                         internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler)
133       : service_manager_(service_manager), link_manager_(link_manager), l2cap_layer_handler_(l2cap_layer_handler) {
134     ASSERT(service_manager_ != nullptr);
135     ASSERT(link_manager_ != nullptr);
136     ASSERT(l2cap_layer_handler_ != nullptr);
137   }
138   internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr;
139   internal::LinkManager* link_manager_ = nullptr;
140   os::Handler* l2cap_layer_handler_ = nullptr;
141   DISALLOW_COPY_AND_ASSIGN(DynamicChannelManager);
142 };
143 
144 }  // namespace le
145 }  // namespace l2cap
146 }  // namespace bluetooth
147