1 // Copyright 2023 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_sapphire/internal/host/gap/adapter_state.h"
18 #include "pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci/sequential_command_runner.h"
20 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
21 
22 namespace bt {
23 namespace hci {
24 class Transport;
25 }  // namespace hci
26 
27 namespace gap {
28 
29 // LowEnergyInterrogator sends HCI commands that request the controller version
30 // and features of a peer and handles responses by updating the Peer.
31 // LowEnergyInterrogator must only be used with an LE or dual mode controller.
32 class LowEnergyInterrogator final {
33  public:
34   // |peer| must outlive this object.
35   // |sca_supported| indicates that the controller supports interrogation of
36   //  peer sleep clock accuracy.
37   LowEnergyInterrogator(Peer::WeakPtr peer,
38                         hci_spec::ConnectionHandle handle,
39                         hci::CommandChannel::WeakPtr hci,
40                         bool sca_supported);
41 
42   // Destroying the LowEnergyInterrogator effectively abandons an in-flight
43   // interrogation, if there is one. The result callback will not be called.
44   ~LowEnergyInterrogator() = default;
45 
46   // Starts interrogation. Calls |callback| when the sequence is completed or
47   // fails. Only 1 interrogation may be pending at a time.
48   using ResultCallback = hci::ResultCallback<>;
49   void Start(ResultCallback callback);
50 
51   // Abandons interrogation. The result callbacks will be called with result of
52   // kCanceled. No-op if interrogation has already completed.
53   void Cancel();
54 
55  private:
56   void Complete(hci::Result<> result);
57 
58   void QueueRequestPeerSca();
59   void QueueReadLERemoteFeatures();
60   void QueueReadRemoteVersionInformation();
61 
62   Peer::WeakPtr peer_;
63   // Cache of the PeerId to allow for debug logging even if the WeakPtr<Peer> is
64   // invalidated
65   const PeerId peer_id_;
66   const hci_spec::ConnectionHandle handle_;
67 
68   ResultCallback callback_ = nullptr;
69 
70   hci::SequentialCommandRunner cmd_runner_;
71 
72   // Controller supports interrogation of peer sleep clock accuracy.
73   bool controller_supports_sca_;
74 
75   // Keep this as the last member to make sure that all weak pointers are
76   // invalidated before other members get destroyed.
77   WeakSelf<LowEnergyInterrogator> weak_self_;
78 
79   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyInterrogator);
80 };
81 
82 }  // namespace gap
83 }  // namespace bt
84