1 // Copyright 2024 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_async2/dispatcher.h" 18 #include "pw_async2/once_sender.h" 19 #include "pw_bluetooth/vendor.h" 20 #include "pw_channel/channel.h" 21 #include "pw_function/function.h" 22 #include "pw_result/result.h" 23 #include "pw_status/status.h" 24 25 namespace pw::bluetooth { 26 27 /// The Controller class is a shim for communication between the Host and the 28 /// Controller. Controller is a `pw::Channel` used to send and receive HCI 29 /// packets. The first byte of each datagram is a UART packet indicator 30 /// (`H4PacketType` Emboss enum). 31 class Controller2 32 : public pw::channel::Implement<pw::channel::ReliableDatagramReaderWriter> { 33 public: 34 /// Bitmask of features the controller supports. 35 enum class FeaturesBits : uint32_t { 36 /// Indicates support for transferring Synchronous Connection-Oriented (SCO) 37 /// link data over the HCI. Offloaded SCO links may still be supported even 38 /// if HCI 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 43 /// documented at 44 /// [HCI 45 /// requirements](https://source.android.com/docs/core/connect/bluetooth/hci_requirements). 46 kAndroidVendorExtensions = (1 << 2), 47 /// Bits 3-31 reserved. 48 }; 49 50 enum class ScoCodingFormat : uint8_t { 51 kCvsd, 52 kMsbc, 53 }; 54 55 enum class ScoEncoding : uint8_t { 56 k8Bits, 57 k16Bits, 58 }; 59 60 enum class ScoSampleRate : uint8_t { 61 k8Khz, 62 k16Khz, 63 }; 64 65 /// Returns Ready when fatal errors occur after initialization. After a fatal 66 /// error, this object is invalid. 67 virtual async2::Poll<Status> PendError(async2::Context& cx) = 0; 68 69 /// Initializes the controller interface and starts processing packets. 70 /// Asynchronously returns the result of initialization. 71 /// 72 /// On success, HCI packets may now be sent and received with this object. 73 virtual async2::OnceReceiver<Status> Initialize() = 0; 74 75 /// Configure the HCI for a SCO connection with the indicated parameters. 76 /// @returns 77 /// * OK - success, packets can be sent/received. 78 /// * UNIMPLEMENTED - the implementation/controller does not support SCO over 79 /// HCI 80 /// * ALREADY_EXISTS - a SCO connection is already configured 81 /// * INTERNAL - an internal error occurred 82 virtual async2::OnceReceiver<Status> ConfigureSco( 83 ScoCodingFormat coding_format, 84 ScoEncoding encoding, 85 ScoSampleRate sample_rate) = 0; 86 87 /// Releases the resources held by an active SCO connection. This should be 88 /// called when a SCO connection is closed. No-op if no SCO connection is 89 /// configured. 90 /// @returns 91 /// * OK - success, the SCO configuration was reset. 92 /// * UNIMPLEMENTED - the implementation/controller does not support SCO over 93 /// * HCI INTERNAL - an internal error occurred 94 virtual async2::OnceReceiver<Status> ResetSco() = 0; 95 96 /// @returns A bitmask of features supported by the controller. 97 virtual async2::OnceReceiver<FeaturesBits> GetFeatures() = 0; 98 99 /// Encode the vendor-specific HCI command for a generic type of vendor 100 /// command, and return the encoded command in a buffer. 101 /// @param parameters Vendor command to encode. 102 /// @returns Returns the result of the encoding request. On success, contains 103 /// the command buffer. 104 virtual async2::OnceReceiver<Result<multibuf::MultiBuf>> EncodeVendorCommand( 105 VendorCommandParameters parameters) = 0; 106 }; 107 108 inline constexpr bool operator&(Controller2::FeaturesBits left, 109 Controller2::FeaturesBits right) { 110 return static_cast<bool>( 111 static_cast<std::underlying_type_t<Controller2::FeaturesBits>>(left) & 112 static_cast<std::underlying_type_t<Controller2::FeaturesBits>>(right)); 113 } 114 115 inline constexpr Controller2::FeaturesBits operator|( 116 Controller2::FeaturesBits left, Controller2::FeaturesBits right) { 117 return static_cast<Controller2::FeaturesBits>( 118 static_cast<std::underlying_type_t<Controller2::FeaturesBits>>(left) | 119 static_cast<std::underlying_type_t<Controller2::FeaturesBits>>(right)); 120 } 121 122 inline constexpr Controller2::FeaturesBits& operator|=( 123 Controller2::FeaturesBits& left, Controller2::FeaturesBits right) { 124 return left = left | right; 125 } 126 127 } // namespace pw::bluetooth 128