// 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.
interface 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|.
  1: 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.
  2: OnReadValue(uint64 id, int32 offset) -> (vector<uint8>? value, ErrorCode status);

  // Called when a remote device issues a request to write the value of the
  // characteristic or descriptor with the given identifier.
  3: OnWriteValue(uint64 id, uint16 offset, vector<uint8> 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.
  4: OnWriteWithoutResponse(uint64 id, uint16 offset, vector<uint8> value);
};

// Interface for communicating with a published service.
interface LocalService {
  // Removes the service that this interface instance corresponds to. Does
  // nothing if the service is already removed.
  1: 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.
  2: NotifyValue(uint64 characteristic_id, string peer_id, vector<uint8> value, bool confirm);
};

[Discoverable]
interface 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.
  1: PublishService(ServiceInfo info, LocalServiceDelegate delegate, request<LocalService> service) -> (fuchsia.bluetooth.Status status);
};
