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