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 #pragma once 15 16 #include "pw_async2/dispatcher.h" 17 #include "pw_async2/once_sender.h" 18 #include "pw_bluetooth/internal/raii_ptr.h" 19 #include "pw_channel/channel.h" 20 #include "pw_result/result.h" 21 22 namespace pw::bluetooth::low_energy { 23 24 /// An identifier for a service that accepts connection-oriented channel 25 /// connections. Referred to as a (simplified) protocol/service multiplexer 26 /// in the Bluetooth specification. 27 enum class Psm : uint16_t {}; 28 29 /// The authentication an encryption requirements for a channel. 30 struct SecurityRequirements { 31 /// If true, the link must be authenticated with on-path attacker protection. 32 /// If false, authentication is not required. 33 bool authentication_required; 34 35 /// If true, the link must be encrypted with a Secure Connections key. 36 bool secure_connections_required; 37 }; 38 39 /// A duplex datagram channel that models the lifetime of a connection-oriented 40 /// channel. Closing or destroying `Channel` will close the underlying channel. 41 class Channel : public pw::channel::ReliableDatagramReaderWriter { 42 public: 43 virtual ~Channel() = default; 44 45 /// Maximum payload size (SDU) that the peer supports receiving. 46 virtual uint16_t max_transmit_size() = 0; 47 48 /// Maximum payload size (SDU) that this channel supports receiving. 49 virtual uint16_t max_receive_size() = 0; 50 51 private: 52 virtual void Release() = 0; 53 54 public: 55 using Ptr = internal::RaiiPtr<Channel, &Channel::Release>; 56 }; 57 58 /// Represents a service or protocol that accepts incoming channels for a PSM. 59 /// Destroying this object will cease accepting any incoming channels, but 60 /// existing established channels will not be affected. Additionally, once 61 /// this object is destroyed the implementation is free to reuse the PSM that 62 /// was previously assigned for this instance. 63 class ChannelListener { 64 public: 65 virtual ~ChannelListener() = default; 66 67 /// Poll to receive incoming channels. 68 virtual async2::Poll<Channel::Ptr> PendChannel(async2::Waker&& waker) = 0; 69 70 /// The protocol/service multiplexer for this listener. 71 virtual Psm psm() = 0; 72 73 private: 74 /// Custom deleter called when `ChannelListener::Ptr` is destroyed. The 75 /// implementation should free or clean up the memory used by this 76 /// object. This enables the use of smart pointer semantics while leaving 77 /// memory management up to the implementation. Calling the virtual destructor 78 /// or not is up to the implementation. 79 virtual void Release() = 0; 80 81 public: 82 using Ptr = internal::RaiiPtr<ChannelListener, &ChannelListener::Release>; 83 }; 84 85 class ChannelListenerRegistry { 86 public: 87 /// The parameters to use for incoming channels. 88 struct ListenParameters { 89 /// Maximum supported payload size (SDU) for receiving. 90 uint16_t max_receive_size; 91 /// The security requirements that must be met before data is exchanged on 92 /// the channel. If the requirements cannot be met, channel establishment 93 /// will fail. 94 SecurityRequirements security_requirements; 95 }; 96 97 virtual ~ChannelListenerRegistry() = default; 98 99 /// Register a listener for incoming channels. The registry will assign a 100 /// protocol/service multiplexer value that is unique for the local device, as 101 /// well as create a `ChannelListener` for accepting incoming channels. In the 102 /// unlikely event that all PSMs have been assigned, this call will fail with 103 /// `RESOURCE_EXHAUSTED`. 104 /// 105 /// Note that the method of service discovery or advertising is defined by 106 /// the service or protocol, so it is the responsibility of the caller to 107 /// update the GATT database or other service discovery mechanism. 108 /// 109 /// @param parameters Parameters for the local side of the channel. 110 /// @return The result of starting the listener. On success, contains a 111 /// `ChannelListener` that can be used to receive new channels. 112 virtual async2::OnceReceiver<pw::Result<ChannelListener::Ptr>> ListenL2cap( 113 ListenParameters parameters) = 0; 114 }; 115 116 } // namespace pw::bluetooth::low_energy 117