xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/pairing_delegate2.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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_bluetooth/internal/raii_ptr.h"
18 #include "pw_bluetooth/peer.h"
19 
20 namespace pw::bluetooth {
21 
22 /// Pairing event handler implemented by the API client.
23 class PairingDelegate2 {
24  public:
25   /// Request models an active pairing procedure.
26   class Request {
27    public:
28     enum class KeypressEvent : uint8_t {
29       /// The user has entered a single digit.
30       kDigitEntered,
31 
32       /// The user has erased a single digit.
33       kDigitErased,
34 
35       /// The user has cleared the entire passkey.
36       kPasskeyCleared,
37 
38       /// The user has finished entering the passkey.
39       kPasskeyEntered
40     };
41 
42     /// Indicates what type of interaction is required locally.
43     enum class Method {
44       /// The user is asked to accept or reject pairing.
45       /// This is the minimum method - even when both devices do not support
46       /// input or output, the delegate will be asked to confirm any pairing
47       /// not initiated with user intent.
48       kConsent,
49       /// The user is shown a 6-digit numerical passkey on this device which
50       /// they
51       /// must key in on the peer device.
52       /// The passkey to be displayed is provided.
53       kPasskeyDisplay,
54       /// The user is shown a 4-digit numerical pin on this device which they
55       /// must key in on the peer device.
56       /// The passkey to be displayed is provided.
57       kPinDisplay,
58       /// The user is shown a 6-digit numerical passkey on this device which
59       /// will also be shown on the peer device. The user must compare the
60       /// passkeys and accept the pairing if the passkeys match.
61       /// The passkey to be displayed is provided.
62       kPasskeyConfirmation,
63       /// The user is asked to enter a 6-digit passkey on this device which is
64       /// communicated via the peer device.
65       kPasskeyEntry,
66       /// The user is asked to enter a 4-digit pin on this device which is
67       /// communicated via the peer device.
68       kPinEntry,
69     };
70 
71     virtual ~Request() = default;
72 
73     /// The peer that initiated the pairing request.
74     virtual Peer peer() = 0;
75 
76     /// Indicates what pairing interaction is required locally.
77     virtual Method method() = 0;
78 
79     /// If the pairing method requires a passkey to be displayed
80     /// (`Method::*Display`, `Method::*Confirmation`), this method returns the
81     /// passkey. Returns null otherwise.
82     virtual std::optional<uint32_t> passkey() = 0;
83 
84     /// Accept the pairing request.
85     /// @param entered_passkey Required if `Method::*Entry` is used.
86     virtual void Accept(std::optional<uint32_t> entered_passkey) = 0;
87 
88     /// Reject the pairing request.
89     virtual void Reject() = 0;
90 
91     /// Used to communicate local keypresses to update the remote peer on
92     /// the progress of the pairing.
93     virtual void Keypress(KeypressEvent keypress) = 0;
94 
95     /// When the pairing method is passkey_display, can be used to update the UI
96     /// to indicate reception of keypresses. Awakens `cx` on the next keypress.
97     virtual async2::Poll<KeypressEvent> PendKeypress(async2::Context& cx) = 0;
98 
99     /// Ready when the pairing is completed. The `Request` should be
100     /// destroyed once pairing is complete. Awakens `cx` on pairing completion.
101     ///
102     /// @return @rst
103     ///
104     /// .. pw-status-codes::
105     ///
106     ///    OK: Pairing completed successfully.
107     ///
108     ///    CANCELLED: Pairing was rejected via `Reject()` or the peer cancelled
109     ///    the pairing.
110     ///
111     ///    DEADLINE_EXCEEDED: Pairing timed out.
112     ///
113     ///    INTERNAL: Pairing failed unexpectedly due to an internal error.
114     ///
115     /// @endrst
116     virtual async2::Poll<pw::Status> PendComplete(async2::Context& cx) = 0;
117 
118    private:
119     /// Reject the request if it is not complete yet and release resources. This
120     /// method is called by the ~Request::Ptr() when it goes out of scope, the
121     /// API client should never call this method.
122     virtual void Release() = 0;
123 
124    public:
125     /// Movable Request smart pointer.
126     using Ptr = internal::RaiiPtr<Request, &Request::Release>;
127   };
128 
129   virtual ~PairingDelegate2() = default;
130 
131   /// Called when a pairing is started with the a peer. The pairing process is
132   /// continued using `request`.
133   ///
134   /// `Request::method()` indicates how the request should be responded to.
135   ///
136   /// Multiple requests can be active at one time for different peers.
137   /// Destroying `request` will automatically reject the pairing.
138   virtual void OnRequest(Request::Ptr&& request) = 0;
139 };
140 
141 }  // namespace pw::bluetooth
142