• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     // Bits 3-31 reserved.
47   };
48 
49   enum class ScoCodingFormat : uint8_t {
50     kCvsd,
51     kMsbc,
52   };
53 
54   enum class ScoEncoding : uint8_t {
55     k8Bits,
56     k16Bits,
57   };
58 
59   enum class ScoSampleRate : uint8_t {
60     k8Khz,
61     k16Khz,
62   };
63 
64   // Closes the controller. `Close` should be called first to safely clean up
65   // state (which may be an asynchronous process).
66   virtual ~Controller() = default;
67 
68   // Sets a function that will be called with HCI event packets received from
69   // the controller. This should  be called before `Initialize` or else incoming
70   // packets will be dropped. The lifetime of data passed to `func` is only
71   // guaranteed for the lifetime of the function call.
72   virtual void SetEventFunction(DataFunction func) = 0;
73 
74   // Sets a function that will be called with ACL data packets received from the
75   // controller. This should be called before `Initialize` or else incoming
76   // packets will be dropped. The lifetime of data passed to `func` is only
77   // guaranteed for the lifetime of the function call.
78   virtual void SetReceiveAclFunction(DataFunction func) = 0;
79 
80   // Sets a function that will be called with SCO packets received from the
81   // controller. On Classic and Dual Mode stacks, this should be called before
82   // `Initialize` or else incoming packets will be dropped. The lifetime of data
83   // passed to `func` is only guaranteed for the lifetime of the function call.
84   virtual void SetReceiveScoFunction(DataFunction func) = 0;
85 
86   // Initializes the controller interface and starts processing packets.
87   // `complete_callback` will be called with the result of initialization.
88   // `error_callback` will be called for fatal errors that occur after
89   // initialization. After a fatal error, this object is invalid. `Close` should
90   // be called to ensure a safe clean up.
91   virtual void Initialize(Callback<void(Status)> complete_callback,
92                           Callback<void(Status)> error_callback) = 0;
93 
94   // Closes the controller interface, resetting all state. `callback` will be
95   // called when closure is complete. After this method is called, this object
96   // should be considered invalid and no other methods should be called
97   // (including `Initialize`).
98   // `callback` will be called with:
99   // OK - the controller interface was successfully closed, or is already closed
100   // INTERNAL - the controller interface could not be closed
101   virtual void Close(Callback<void(Status)> callback) = 0;
102 
103   // Sends an HCI command packet to the controller.
104   virtual void SendCommand(span<const std::byte> command) = 0;
105 
106   // Sends an ACL data packet to the controller.
107   virtual void SendAclData(span<const std::byte> data) = 0;
108 
109   // Sends a SCO data packet to the controller.
110   virtual void SendScoData(span<const std::byte> data) = 0;
111 
112   // Configure the HCI for a SCO connection with the indicated parameters.
113   // `SetReceiveScoFunction` must be called before calling this method.
114   // `callback will be called with:
115   // OK - success, packets can be sent/received.
116   // UNIMPLEMENTED - the implementation/controller does not support SCO over HCI
117   // ALREADY_EXISTS - a SCO connection is already configured
118   // INTERNAL - an internal error occurred
119   virtual void ConfigureSco(ScoCodingFormat coding_format,
120                             ScoEncoding encoding,
121                             ScoSampleRate sample_rate,
122                             Callback<void(Status)> callback) = 0;
123 
124   // Releases the resources held by an active SCO connection. This should be
125   // called when a SCO connection is closed. `ConfigureSco` must be called
126   // before calling this method.
127   // `callback will be called with:
128   // OK - success, the SCO configuration was reset.
129   // UNIMPLEMENTED - the implementation/controller does not support SCO over HCI
130   // INTERNAL - an internal error occurred
131   virtual void ResetSco(Callback<void(Status)> callback) = 0;
132 
133   // Calls `callback` with a bitmask of features supported by the controller.
134   virtual void GetFeatures(Callback<void(FeaturesBits)> callback) = 0;
135 
136   // Encodes the vendor command indicated by `parameters`.
137   // `callback` will be called with the result of the encoding request.
138   // The lifetime of data passed to `callback` is only guaranteed for the
139   // lifetime of the function call.
140   virtual void EncodeVendorCommand(
141       VendorCommandParameters parameters,
142       Callback<void(Result<span<const std::byte>>)> callback) = 0;
143 };
144 
145 inline constexpr bool operator&(Controller::FeaturesBits left,
146                                 Controller::FeaturesBits right) {
147   return static_cast<bool>(
148       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(left) &
149       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(right));
150 }
151 
152 inline constexpr Controller::FeaturesBits operator|(
153     Controller::FeaturesBits left, Controller::FeaturesBits right) {
154   return static_cast<Controller::FeaturesBits>(
155       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(left) |
156       static_cast<std::underlying_type_t<Controller::FeaturesBits>>(right));
157 }
158 
159 inline constexpr Controller::FeaturesBits& operator|=(
160     Controller::FeaturesBits& left, Controller::FeaturesBits right) {
161   return left = left | right;
162 }
163 
164 }  // namespace pw::bluetooth
165