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 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h" 17 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h" 18 #include "pw_bluetooth_sapphire/internal/host/transport/error.h" 19 20 namespace bt::hci { 21 22 // The request can be in three possible states: 23 enum class RequestState : uint8_t { 24 // The connection request is still pending 25 kPending, 26 // The connection request was intentionally cancelled 27 kCanceled, 28 // The connection request timed out whilst waiting for a response 29 kTimedOut, 30 // The connection request has succeeded 31 kSuccess, 32 }; 33 34 // Bitmask enabling all packets types. By enabling as many as we can, we expect 35 // the controller to only use the ones it supports 36 constexpr hci_spec::PacketTypeType kEnableAllPacketTypes = 37 static_cast<hci_spec::PacketTypeType>( 38 hci_spec::PacketTypeBits::kEnableDM1) | 39 static_cast<hci_spec::PacketTypeType>( 40 hci_spec::PacketTypeBits::kEnableDH1) | 41 static_cast<hci_spec::PacketTypeType>( 42 hci_spec::PacketTypeBits::kEnableDM3) | 43 static_cast<hci_spec::PacketTypeType>( 44 hci_spec::PacketTypeBits::kEnableDH3) | 45 static_cast<hci_spec::PacketTypeType>( 46 hci_spec::PacketTypeBits::kEnableDM5) | 47 static_cast<hci_spec::PacketTypeType>(hci_spec::PacketTypeBits::kEnableDH5); 48 49 // This class represents a pending request by the BrEdr connector to initiate an 50 // outgoing connection. It tracks the state of that request and is responsible 51 // for running a call back when the connection status updates 52 // 53 // There should be only one of these at any given time, an it is managed by the 54 // BrEdrConnectionManager 55 class BrEdrConnectionRequest final { 56 public: 57 using OnCompleteDelegate = fit::function<void(Result<>, PeerId)>; 58 BrEdrConnectionRequest(PeerId id,DeviceAddress addr,fit::closure timeout_callback,pw::async::Dispatcher & dispatcher)59 BrEdrConnectionRequest(PeerId id, 60 DeviceAddress addr, 61 fit::closure timeout_callback, 62 pw::async::Dispatcher& dispatcher) 63 : state_(RequestState::kPending), 64 peer_id_(id), 65 peer_address_(addr), 66 timeout_task_(dispatcher), 67 weak_self_(this) { 68 timeout_task_.set_function( 69 [timeout_cb = std::move(timeout_callback)](pw::async::Context /*ctx*/, 70 pw::Status status) { 71 if (status.ok()) { 72 timeout_cb(); 73 } 74 }); 75 } 76 77 ~BrEdrConnectionRequest(); 78 79 // Send the CreateConnection command over |command_channel| and begin the 80 // create connection procedure. If the command status returns an error, then 81 // |on_command_fail| called. The |clock_offset| and |page_scan_repetition| 82 // parameters are standard parameters found in Core Spec 5.0, Vol 2, Part E, 83 // section 7.1.5 84 // |timeout| is the command timeout; this is how long we give from the point 85 // we receive the CommandStatus response from the controller until we cancel 86 // the procedure if we have not received ConnectionComplete 87 void CreateConnection( 88 CommandChannel* command_channel, 89 std::optional<uint16_t> clock_offset, 90 std::optional<pw::bluetooth::emboss::PageScanRepetitionMode> 91 page_scan_repetition_mode, 92 pw::chrono::SystemClock::duration timeout, 93 OnCompleteDelegate on_command_fail); 94 peer_id()95 PeerId peer_id() const { return peer_id_; } peer_address()96 DeviceAddress peer_address() const { return peer_address_; } 97 98 // Complete the request, either successfully or not, and return the status 99 // of the Request - In the case of Timeout or Cancellation, this will be 100 // different from the status sent by the controller. 101 Result<> CompleteRequest(Result<> status); 102 103 // Mark the request as Timed out; triggered when the command timeout runs out 104 // and called by BrEdrConnectionManager; 105 void Timeout(); 106 107 // Attempt to mark the request as Canceled, and returns true if successful. 108 // This is called during cleanup to ensure connection procedures are not 109 // orphaned 110 bool Cancel(); 111 112 private: 113 RequestState state_; 114 PeerId peer_id_; 115 DeviceAddress peer_address_; 116 117 SmartTask timeout_task_; 118 119 // Keep this as the last member to make sure that all weak pointers are 120 // invalidated before other members get destroyed. 121 WeakSelf<BrEdrConnectionRequest> weak_self_; 122 }; 123 124 } // namespace bt::hci 125