blob: 1e965d67dac259ca3f76f5f814d95b31afd3b2c8 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_BREDR_INTERROGATOR_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_BREDR_INTERROGATOR_H_
#include <fbl/macros.h>
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include <lib/fit/function.h>
#include <memory>
#include "src/connectivity/bluetooth/core/bt-host/common/device_address.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/command_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection_parameters.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/control_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci_constants.h"
#include "src/lib/fxl/functional/cancelable_callback.h"
#include "src/lib/fxl/memory/ref_ptr.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/lib/fxl/synchronization/thread_checker.h"
namespace bt {
namespace hci {
class Transport;
}
namespace gap {
// A BrEdrInterrogator abstracts over the HCI commands and events involved
// immediately after connecting to a remote device over BR/EDR.
// It also provides a way to hold pending connections while waiting for
// confirmation and times out those connections out when we do not get a
// response.
//
// This class owns a Connection object while interrogation happens.
//
// Only one interregator object is expected to exist per controller.
class BrEdrInterrogator {
public:
// |cache| must live longer than this object.
BrEdrInterrogator(PeerCache* cache, fxl::RefPtr<hci::Transport> hci,
async_dispatcher_t* dispatcher);
// Will cancel all uncompleted interrogations.
~BrEdrInterrogator();
// Starts interrogation. Calls |callback| when the sequence is completed or
// abandoned.
using ResultCallback =
fit::function<void(hci::Status status, hci::ConnectionPtr conn_ptr)>;
void Start(PeerId device_id, hci::ConnectionPtr conn_ptr,
ResultCallback callback);
// Abandons any interrogation of |device_id|. Their callbacks will be called
// with a Status of Canceled.
void Cancel(PeerId device_id);
private:
// Completes |device| if there is nothing else to ask.
void MaybeComplete(PeerId device_id);
// Completes interrogation on |device| with |status|, possibly early.
void Complete(PeerId device_id, hci::Status status);
// Reade the remote version information from the device.
void ReadRemoteVersionInformation(PeerId device_id,
hci::ConnectionHandle handle);
// Requests the name of the remote device.
void MakeRemoteNameRequest(PeerId device_id);
// Requests features of |device|, and asks for Extended Features if they
// exist.
void ReadRemoteFeatures(PeerId device_id, hci::ConnectionHandle handle);
// Reads the extended feature page |page| of |device|.
void ReadRemoteExtendedFeatures(PeerId device_id,
hci::ConnectionHandle handle, uint8_t page);
using CancelableCommandCallback = fxl::CancelableCallback<void(
hci::CommandChannel::TransactionId id, const hci::EventPacket& event)>;
struct Interrogation {
Interrogation(hci::ConnectionPtr conn_ptr, ResultCallback callback);
~Interrogation();
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Interrogation);
// Connection to |device|
hci::ConnectionPtr conn_ptr;
// Callback for results.
ResultCallback result_cb;
// Set of callbacks we cancel if we stop the interrogation.
std::deque<CancelableCommandCallback> callbacks;
// Finishes the interrogation, calling the callback.
void Finish(hci::Status status);
};
// The hci transport to use.
fxl::RefPtr<hci::Transport> hci_;
// The dispatcher we use.
async_dispatcher_t* dispatcher_;
// Cache to retrieve devices from.
PeerCache* cache_;
// The current set of interrogations
// TODO(BT-750): Store Interrogations by value.
std::unordered_map<PeerId, std::unique_ptr<Interrogation>> pending_;
// Keep this as the last member to make sure that all weak pointers are
// invalidated before other members get destroyed.
fxl::WeakPtrFactory<BrEdrInterrogator> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrInterrogator);
};
} // namespace gap
} // namespace bt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_BREDR_INTERROGATOR_H_