blob: fef0ecd4fdf69c809e8751c7be1d3757e6df6cc6 [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 GARNET_DRIVERS_BLUETOOTH_LIB_GATT_REMOTE_SERVICE_MANAGER_H_
#define GARNET_DRIVERS_BLUETOOTH_LIB_GATT_REMOTE_SERVICE_MANAGER_H_
#include <map>
#include <memory>
#include <vector>
#include <fbl/ref_ptr.h>
#include <lib/async/dispatcher.h>
#include <zircon/assert.h>
#include "garnet/drivers/bluetooth/lib/att/status.h"
#include "garnet/drivers/bluetooth/lib/gatt/gatt.h"
#include "garnet/drivers/bluetooth/lib/gatt/remote_service.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
namespace btlib {
namespace gatt {
class Client;
namespace internal {
// Maintains a collection of services that are present on a particular peer
// device. The RemoteServiceManager owns the GATT client data bearer, interacts
// with the profile-defined GATT service, and allows observers to be notified
// as services get discovered.
//
// THREAD SAFETY:
//
// This class is NOT thread safe. It must be created, used, and destroyed on a
// specific thread.
class RemoteServiceManager final {
public:
RemoteServiceManager(std::unique_ptr<Client> client,
async_dispatcher_t* gatt_dispatcher);
~RemoteServiceManager();
// Adds a handler to be notified when a new service is added.
void set_service_watcher(RemoteServiceWatcher watcher) {
ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
svc_watcher_ = std::move(watcher);
}
// Initiates the Exchange MTU procedure followed by primary service
// discovery. |callback| is called to notify the result of the procedure.
void Initialize(att::StatusCallback callback);
// Returns a vector containing discovered services that match any of the given
// |uuids| via |callback|. All services will be returned if |uuids| is empty.
//
// If called while uninitialized, |callback| will be run after initialization.
void ListServices(const std::vector<common::UUID>& uuids,
ServiceListCallback callback);
// Returns the RemoteService with the requested range start |handle| or
// nullptr if it is not recognized. This method may fail if called before or
// during initialization.
fbl::RefPtr<RemoteService> FindService(att::Handle handle);
private:
using ServiceMap = std::map<att::Handle, fbl::RefPtr<RemoteService>>;
// Used to represent a queued ListServices() request.
class ServiceListRequest {
public:
ServiceListRequest(ServiceListCallback callback,
const std::vector<common::UUID>& uuids);
ServiceListRequest() = default;
ServiceListRequest(ServiceListRequest&&) = default;
// Completes this request by using entries from |services| that match any of
// the requested UUIDs.
void Complete(att::Status status, const ServiceMap& services);
private:
ServiceListCallback callback_;
std::vector<common::UUID> uuids_;
FXL_DISALLOW_COPY_AND_ASSIGN(ServiceListRequest);
};
// Shuts down and cleans up all services.
void ClearServices();
// Called by |client_| when a notification or indication is received.
void OnNotification(bool ind, att::Handle value_handle,
const common::ByteBuffer& value);
async_dispatcher_t* gatt_dispatcher_;
std::unique_ptr<Client> client_;
bool initialized_;
RemoteServiceWatcher svc_watcher_;
// Requests queued during calls ListServices() before initialization.
std::queue<ServiceListRequest> pending_;
// Services are sorted by handle.
ServiceMap services_;
fxl::ThreadChecker thread_checker_;
fxl::WeakPtrFactory<RemoteServiceManager> weak_ptr_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(RemoteServiceManager);
};
} // namespace internal
} // namespace gatt
} // namespace btlib
#endif // GARNET_DRIVERS_BLUETOOTH_LIB_GATT_REMOTE_SERVICE_MANAGER_H_