| // 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_GATT_H_ |
| #define GARNET_DRIVERS_BLUETOOTH_LIB_GATT_GATT_H_ |
| |
| #include <fbl/ref_counted.h> |
| #include <fbl/ref_ptr.h> |
| #include <lib/async/dispatcher.h> |
| #include <lib/fit/function.h> |
| |
| #include "garnet/drivers/bluetooth/lib/common/uuid.h" |
| #include "garnet/drivers/bluetooth/lib/gatt/gatt_defs.h" |
| #include "garnet/drivers/bluetooth/lib/gatt/local_service_manager.h" |
| #include "garnet/drivers/bluetooth/lib/gatt/remote_service.h" |
| #include "garnet/drivers/bluetooth/lib/gatt/types.h" |
| |
| #include "lib/fidl/cpp/vector.h" |
| #include "lib/fxl/memory/ref_ptr.h" |
| |
| namespace btlib { |
| |
| namespace l2cap { |
| class Channel; |
| } // namespace l2cap |
| |
| namespace gatt { |
| |
| // This is the root object of the GATT layer. This object owns: |
| // |
| // * A single local attribute database |
| // * All client and server data bearers |
| // * L2CAP ATT fixed channels |
| // |
| // GATT requires an dispatcher on initialization which will be used to |
| // serialize all internal GATT tasks. |
| // |
| // All public functions are asynchronous and thread-safe. |
| class GATT : public fbl::RefCounted<GATT> { |
| public: |
| // Constructs a GATT object. |
| static fbl::RefPtr<GATT> Create(async_dispatcher_t* gatt_dispatcher); |
| |
| // Initialize/ShutDown the GATT profile. It is safe for the caller to drop its |
| // reference after ShutDown. |
| // |
| // The owner MUST call ShutDown() to properly clean up the object. |
| virtual void Initialize() = 0; |
| virtual void ShutDown() = 0; |
| |
| // Registers the given connection with the GATT profile without initiating |
| // service discovery. Once a connection is registered with GATT, the peer can |
| // access local services and clients can call the "Remote Service" methods |
| // below using |peer_id|. |
| // |
| // |peer_id|: The identifier for the peer device that the link belongs to. |
| // This is used to identify the peer while handling certain events. |
| // |att_chan|: The ATT fixed channel over which the ATT protocol bearer will |
| // operate. The bearer will be associated with the link that |
| // underlies this channel. |
| virtual void AddConnection(const std::string& peer_id, |
| fbl::RefPtr<l2cap::Channel> att_chan) = 0; |
| |
| // Unregisters the GATT profile connection to the peer with Id |peer_id|. |
| virtual void RemoveConnection(std::string peer_id) = 0; |
| |
| // ============== |
| // Local Services |
| // ============== |
| // |
| // The methods below are for managing local GATT services that are available |
| // to data bearers in the server role. |
| |
| // Registers the GATT service hierarchy represented by |service| with the |
| // local attribute database. Once successfully registered, the service will |
| // be available to remote clients. |
| // |
| // Objects under |service| must have unique identifiers to aid in value |
| // request handling. These identifiers will be passed to |read_handler| and |
| // |write_handler|. |
| // |
| // The provided handlers will be called to handle remote initiated |
| // transactions targeting the service. These handlers will be run on the |
| // on the GATT dispatcher. |
| // |
| // This method returns an opaque identifier on successful registration, |
| // which can be used by the caller to refer to the service in the future. This |
| // ID will be returned via |callback| which run on the GATT dispatcher. |
| // |
| // Returns |kInvalidId| on failure. Registration can fail if the attribute |
| // database has run out of handles or if the hierarchy contains |
| // characteristics or descriptors with repeated IDs. |
| using ServiceIdCallback = fit::function<void(IdType)>; |
| virtual void RegisterService(ServicePtr service, |
| ServiceIdCallback callback, |
| ReadHandler read_handler, |
| WriteHandler write_handler, |
| ClientConfigCallback ccc_callback) = 0; |
| |
| // Unregisters the GATT service hierarchy identified by |service_id|. Has no |
| // effect if |service_id| is not a registered id. |
| virtual void UnregisterService(IdType service_id) = 0; |
| |
| // Sends a characteristic handle-value notification to a peer that has |
| // configured the characteristic for notifications or indications. Does |
| // nothing if the given peer has not configured the characteristic. |
| // |
| // |service_id|: The GATT service that the characteristic belongs to. |
| // |chrc_id|: The GATT characteristic that will be notified. |
| // |peer_id|: ID of the peer that the notification/indication will be sent to. |
| // |value|: The attribute value that will be included in the notification. |
| // |indicate|: If true, an indication will be sent. |
| // |
| // This method can only be called on the GATT task runner. |
| // |
| // TODO(armansito): Revise this API to involve fewer lookups (NET-483). |
| // TODO(armansito): Fix this to notify all registered peers when |peer_id| is |
| // empty (NET-589). |
| virtual void SendNotification(IdType service_id, |
| IdType chrc_id, |
| std::string peer_id, |
| ::std::vector<uint8_t> value, |
| bool indicate) = 0; |
| |
| // =============== |
| // Remote Services |
| // =============== |
| // |
| // The methods below are for interacting with remote GATT services. These |
| // methods operate asynchronously. |
| |
| // Perform service discovery and initialize remote services for the peer with |
| // the given |peer_id|. |
| virtual void DiscoverServices(std::string peer_id) = 0; |
| |
| // Register a handler that will be notified when a remote service gets |
| // discovered on a connected peer. |
| // |
| // |watcher| will be posted on an dispatcher if one is provided. |
| // Otherwise, it will run on an internal thread and the client is responsible |
| // for synchronization. |
| using RemoteServiceWatcher = |
| fit::function<void(const std::string& peer_id, |
| fbl::RefPtr<RemoteService> service)>; |
| virtual void RegisterRemoteServiceWatcher(RemoteServiceWatcher watcher, |
| async_dispatcher_t* dispatcher = nullptr) = 0; |
| |
| // Returns the list of remote services that were found on the device with |
| // |peer_id|. If |peer_id| was registered but DiscoverServices() has not been |
| // called yet, this request will be buffered until remote services have been |
| // discovered. If the connection is removed without discovery services, |
| // |callback| will be called with an error status. |callback| will always run |
| // on the GATT loop. |
| virtual void ListServices(std::string peer_id, |
| std::vector<common::UUID> uuids, |
| ServiceListCallback callback) = 0; |
| |
| // Connects the RemoteService with the given identifier found on the |
| // device with |peer_id|. Returns nullptr if the service is not found. |
| // |callback| will be run on the given task runner. |
| // |
| // TODO(armansito): Change this to ConnectToService(). |
| virtual void FindService(std::string peer_id, |
| IdType service_id, |
| RemoteServiceCallback callback) = 0; |
| |
| protected: |
| friend class fbl::RefPtr<GATT>; |
| GATT() = default; |
| virtual ~GATT() = default; |
| |
| private: |
| FXL_DISALLOW_COPY_AND_ASSIGN(GATT); |
| }; |
| |
| } // namespace gatt |
| } // namespace btlib |
| |
| #endif // GARNET_DRIVERS_BLUETOOTH_LIB_GATT_GATT_H_ |