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