• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 
17 #pragma once
18 
19 #include <cstdint>
20 #include <optional>
21 
22 #include "hci/address.h"
23 #include "model/setup/async_manager.h"
24 
25 namespace rootcanal {
26 
27 using ::bluetooth::hci::Address;
28 
29 /*
30  * Notes about SCO / eSCO connection establishment:
31  *
32  * - Connections will always be established if possible as eSCO connections.
33  * The LMP parameter negotiation is skipped, instead the required parameters
34  * are directly sent to the peer.
35  *
36  * - If an synchronous connection setup fails with eSCO parameter negotiation,
37  * it is _not_ retried with SCO parameter negotiation.
38  *
39  * - If the parameters are compatible with the values returned from
40  * HCI Accept Synchronous Connection Request on the peer,
41  * the peer selects a valid link configuration which it returns
42  * in response.
43  */
44 
45 struct ScoLinkParameters {
46   uint8_t transmission_interval;
47   uint8_t retransmission_window;
48   uint16_t rx_packet_length;
49   uint16_t tx_packet_length;
50   uint8_t air_mode;
51   bool extended;
52 };
53 
54 struct ScoConnectionParameters {
55   uint32_t transmit_bandwidth;
56   uint32_t receive_bandwidth;
57   uint16_t max_latency;  // 0-3 reserved, 0xFFFF = don't care
58   uint16_t voice_setting;
59   uint8_t retransmission_effort;
60   uint16_t packet_type;
61 
62   // Return true if packet_type enables extended SCO packets.
63   bool IsExtended();
64 
65   // Return the link parameters for these connection parameters, if the
66   // parameters are coherent, none otherwise.
67   std::optional<ScoLinkParameters> GetLinkParameters();
68 };
69 
70 enum ScoState {
71   SCO_STATE_CLOSED = 0,
72   SCO_STATE_PENDING,
73   SCO_STATE_SENT_ESCO_CONNECTION_REQUEST,
74   SCO_STATE_SENT_SCO_CONNECTION_REQUEST,
75   SCO_STATE_OPENED,
76 };
77 
78 enum ScoDatapath {
79   NORMAL = 0,   // data is provided by the host over HCI
80   SPOOFED = 1,  // rootcanal generates data itself
81 };
82 
83 class ScoConnection {
84  public:
ScoConnection(Address address,ScoConnectionParameters const & parameters,ScoState state,ScoDatapath datapath,bool legacy)85   ScoConnection(Address address, ScoConnectionParameters const& parameters,
86                 ScoState state, ScoDatapath datapath, bool legacy)
87       : address_(address),
88         parameters_(parameters),
89         link_parameters_(),
90         state_(state),
91         datapath_(datapath),
92         legacy_(legacy) {}
93 
94   virtual ~ScoConnection() = default;
95 
IsLegacy()96   bool IsLegacy() const { return legacy_; }
GetAddress()97   Address GetAddress() const { return address_; }
GetState()98   ScoState GetState() const { return state_; }
SetState(ScoState state)99   void SetState(ScoState state) { state_ = state; }
100 
101   void StartStream(std::function<AsyncTaskId()> startStream);
102   void StopStream(std::function<void(AsyncTaskId)> stopStream);
103 
GetConnectionParameters()104   ScoConnectionParameters GetConnectionParameters() const {
105     return parameters_;
106   }
GetLinkParameters()107   ScoLinkParameters GetLinkParameters() const { return link_parameters_; }
SetLinkParameters(ScoLinkParameters const & parameters)108   void SetLinkParameters(ScoLinkParameters const& parameters) {
109     link_parameters_ = parameters;
110   }
111 
112   // Negotiate the connection parameters.
113   // Update the local connection parameters with negotiated values.
114   // Return true if the negotiation was successful, false otherwise.
115   bool NegotiateLinkParameters(ScoConnectionParameters const& peer);
116 
GetDatapath()117   ScoDatapath GetDatapath() const { return datapath_; }
118 
119  private:
120   Address address_;
121   ScoConnectionParameters parameters_;
122   ScoLinkParameters link_parameters_;
123   ScoState state_;
124 
125   // whether we use HCI, spoof the data, or potential future datapaths
126   ScoDatapath datapath_;
127 
128   // The handle of the async task managing the SCO stream, used to simulate
129   // offloaded input. None if HCI is used for input packets.
130   std::optional<AsyncTaskId> stream_handle_{};
131 
132   // Mark connections opened with the HCI command Add SCO Connection.
133   // The connection status is reported with HCI Connection Complete event
134   // rather than HCI Synchronous Connection Complete event.
135   bool legacy_;
136 };
137 
138 }  // namespace rootcanal
139