xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/controller.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 
17 #include "pw_bluetooth/vendor.h"
18 #include "pw_containers/vector.h"
19 #include "pw_function/function.h"
20 #include "pw_result/result.h"
21 #include "pw_span/span.h"
22 #include "pw_status/status.h"
23 
24 namespace pw::bluetooth {
25 
26 // The Controller class is a shim for communication between the Host and the
27 // Controller.
28 class Controller {
29  public:
30   // The lifetime of the span is only guaranteed for the lifetime of the
31   // function call.
32   using DataFunction = Function<void(span<const std::byte>)>;
33 
34   // Bitmask of features the controller supports.
35   enum class FeaturesBits : uint32_t {
36     // Indicates support for transferring Synchronous Connection-Oriented link
37     // data over the HCI. Offloaded SCO links may still be supported even if HCI
38     // SCO isn't.
39     kHciSco = (1 << 0),
40     // Indicates support for the Set Acl Priority command.
41     kSetAclPriorityCommand = (1 << 1),
42     // Indicates support for the `LE_Get_Vendor_Capabilities` command documented
43     // at
44     // https://source.android.com/docs/core/connect/bluetooth/hci_requirements
45     kAndroidVendorExtensions = (1 << 2),
46     // Indicates support for Isochronous channels over HCI.
47     kHciIso = (1 << 3),
48     // Bits 4-31 reserved.
49   };
50 
51   enum class ScoCodingFormat : uint8_t {
52     kCvsd,
53     kMsbc,
54   };
55 
56   enum class ScoEncoding : uint8_t {
57     k8Bits,
58     k16Bits,
59   };
60 
61   enum class ScoSampleRate : uint8_t {
62     k8Khz,
63     k16Khz,
64   };
65 
66   // Closes the controller. `Close` should be called first to safely clean up
67   // state (which may be an asynchronous process).
68   virtual ~Controller() = default;
69 
70   // Sets a function that will be called with HCI event packets received from
71   // the controller. This should  be called before `Initialize` or else incoming
72   // packets will be dropped. The lifetime of data passed to `func` is only
73   // guaranteed for the lifetime of the function call.
74   virtual void SetEventFunction(DataFunction func) = 0;
75 
76   // Sets a function that will be called with ACL data packets received from the
77   // controller. This should be called before `Initialize` or else incoming
78   // packets will be dropped. The lifetime of data passed to `func` is only
79   // guaranteed for the lifetime of the function call.
80   virtual void SetReceiveAclFunction(DataFunction func) = 0;
81 
82   // Sets a function that will be called with SCO packets received from the
83   // controller. On Classic and Dual Mode stacks, this should be called before
84   // `Initialize` or else incoming packets will be dropped. The lifetime of data
85   // passed to `func` is only guaranteed for the lifetime of the function call.
86   virtual void SetReceiveScoFunction(DataFunction func) = 0;
87 
88   // Sets a function that will be called with ISO packets received from the
89   // controller. This should be called before an ISO data path is setup or else
90   // incoming packets may be dropped. The lifetime of data passed to `func` is
91   // only guaranteed for the lifetime of the function call.
SetReceiveIsoFunction(DataFunction)92   virtual void SetReceiveIsoFunction(DataFunction /*func*/) {}
93 
94   // Initializes the controller interface and starts processing packets.
95   // `complete_callback` will be called with the result of initialization.
96   // `error_callback` will be called for fatal errors that occur after
97   // initialization. After a fatal error, this object is invalid. `Close` should
98   // be called to ensure a safe clean up.
99   virtual void Initialize(Callback<void(Status)> complete_callback,
100                           Callback<void(Status)> error_callback) = 0;
101 
102   // Closes the controller interface, resetting all state. `callback` will be
103   // called when closure is complete. After this method is called, this object
104   // should be considered invalid and no other methods should be called
105   // (including `Initialize`).
106   // `callback` will be called with:
107   // OK - the controller interface was successfully closed, or is already closed
108   // INTERNAL - the controller interface could not be closed
109   virtual void Close(Callback<void(Status)> callback) = 0;
110 
111   // Sends an HCI command packet to the controller.
112   virtual void SendCommand(span<const std::byte> command) = 0;
113 
114   // Sends an ACL data packet to the controller.
115   virtual void SendAclData(span<const std::byte> data) = 0;
116 
117   // Sends a SCO data packet to the controller.
118   virtual void SendScoData(span<const std::byte> data) = 0;
119 
120   // Sends an ISO data packet to the controller.
SendIsoData(span<const std::byte>)121   virtual void SendIsoData(span<const std::byte> /*data*/) {}
122 
123   // Configure the HCI for a SCO connection with the indicated parameters.
124   // `SetReceiveScoFunction` must be called before calling this method.
125   // `callback will be called with:
126   // OK - success, packets can be sent/received.
127   // UNIMPLEMENTED - the implementation/controller does not support SCO over HCI
128   // ALREADY_EXISTS - a SCO connection is already configured
129   // INTERNAL - an internal error occurred
130   virtual void ConfigureSco(ScoCodingFormat coding_format,
131                             ScoEncoding encoding,
132                             ScoSampleRate sample_rate,
133                             Callback<void(Status)> callback) = 0;
134 
135   // Releases the resources held by an active SCO connection. This should be
136   // called when a SCO connection is closed. `ConfigureSco` must be called
137   // before calling this method.
138   // `callback will be called with:
139   // OK - success, the SCO configuration was reset.
140   // UNIMPLEMENTED - the implementation/controller does not support SCO over HCI
141   // INTERNAL - an internal error occurred
142   virtual void ResetSco(Callback<void(Status)> callback) = 0;
143 
144   // Calls `callback` with a bitmask of features supported by the controller.
145   virtual void GetFeatures(Callback<void(FeaturesBits)> callback) = 0;
146 
147   // Encodes the vendor command indicated by `parameters`.
148   // `callback` will be called with the result of the encoding request.
149   // The lifetime of data passed to `callback` is only guaranteed for the
150   // lifetime of the function call.
151   virtual void EncodeVendorCommand(
152       VendorCommandParameters parameters,
153       Callback<void(Result<span<const std::byte>>)> callback) = 0;
154 };
155 
156 inline constexpr bool operator&(Controller::FeaturesBits left,
157                                 Controller::FeaturesBits right) {
158   return static_cast<bool>(
159       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(left) &
160       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(right));
161 }
162 
163 inline constexpr Controller::FeaturesBits operator|(
164     Controller::FeaturesBits left, Controller::FeaturesBits right) {
165   return static_cast<Controller::FeaturesBits>(
166       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(left) |
167       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(right));
168 }
169 
170 inline constexpr Controller::FeaturesBits& operator|=(
171     Controller::FeaturesBits& left, Controller::FeaturesBits right) {
172   return left = left | right;
173 }
174 
175 }  // namespace pw::bluetooth
176