// Copyright 2017 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.

library fuchsia.bluetooth.gatt;

using fuchsia.bluetooth;

// Interface for responding to requests on a local service.
protocol LocalServiceDelegate {
    // Notifies the delegate when a remote device with |peer_id| enables or
    // disables notifications or indications on the characteristic with the given
    // |characteristic_id|.
    OnCharacteristicConfiguration(uint64 characteristic_id, string peer_id,
                                  bool notify, bool indicate);

    // Called when a remote device issues a request to read the value of the
    // of the characteristic or descriptor with given identifier. The delegate
    // must respond to the request by returning the characteristic value. If the
    // read request resulted in an error it should be returned in |error_code|.
    // On success, |error_code| should be set to NO_ERROR and a |value| should be
    // provided.
    OnReadValue(uint64 id, int32 offset) -> (bytes? value, ErrorCode status);

    // Called when a remote device issues a request to write the value of the
    // characteristic or descriptor with the given identifier.
    OnWriteValue(uint64 id, uint16 offset, bytes value) -> (ErrorCode status);

    // Called when a remote device issues a request to write the value of the
    // characteristic with the given identifier. This can be called on a
    // characteristic with the WRITE_WITHOUT_RESPONSE property.
    OnWriteWithoutResponse(uint64 id, uint16 offset, bytes value);
};

// Interface for communicating with a published service.
protocol LocalService {
    // Removes the service that this interface instance corresponds to. Does
    // nothing if the service is already removed.
    RemoveService();

    // Sends a notification carrying the |value| of the characteristic with the
    // given |characteristic_id| to the device with |peer_id|.
    //
    // If |confirm| is true, then this method sends an indication instead. If the
    // peer fails to confirm the indication, the link between the peer and the
    // local adapter will be closed.
    //
    // This method has no effect if the peer has not enabled notifications or
    // indications on the requested characteristic.
    NotifyValue(uint64 characteristic_id, string peer_id, bytes value, bool confirm);
};

[Discoverable]
protocol Server {
    // Publishes the given service so that it is available to all remote peers.
    // A LocalServiceDelegate must be provided over which to receive service requests.
    //
    // The caller must assign distinct identifiers to the characteristics and
    // descriptors listed in |info|. These identifiers will be used in requests
    // sent to |delegate|.
    //
    // |service| can be used to interact with the pubished service. If this
    // service cannot be published then the handle for |service| will be closed.
    //
    // Returns the success or failure status of the call and a unique identifier
    // that can be used to unregister the service.
    PublishService(ServiceInfo info, LocalServiceDelegate delegate, request<LocalService> service) -> (fuchsia.bluetooth.Status status);
};
