// Copyright 2021 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.gatt2;

using fuchsia.bluetooth as bt;
using zx;

/// The amount of credits defined to be available for sending indications/notifications when a
/// LocalService is first published.
const INITIAL_VALUE_CHANGED_CREDITS uint32 = 10;

/// The parameters used to signal a characteristic value change from a LocalService to a peer.
type ValueChangedParameters = table {
    /// The handle of the characteristic value being signalled.
    /// Mandatory.
    1: handle Handle;
    /// The updated value of the characteristic.
    /// Note for clients using indications/notifications for high-throughput (not recommended):
    /// While statically constrained to `MAX_VALUE_LENGTH`, the real limit depends on the specific
    /// peer's configuration as notified by `LocalService.PeerUpdate`. Any bytes exceeding that
    /// limit are truncated internally by the stack.
    /// Mandatory.
    2: value bytes:MAX_VALUE_LENGTH;
    /// Only signal a subset of peers.  
    /// If not present or empty, all peers that can be updated are signaled.
    /// If included, only the set of peers in this list will be signaled.  
    /// Peers are only signaled if they have configured updates or notifications per `LocalService.`
    /// `CharacteristicConfiguration`; other peers in `peer_ids` will be ignored.
    3: peer_ids vector<bt.PeerId>:MAX;
};

/// Interface for serving a local GATT service. Closing the server_end of this protocol causes the
/// GATT service to be removed from the local GATT database. Similarly, closure of the client_end
/// of this protocol means the Bluetooth stack has removed this service from its GATT database.
protocol LocalService {
    /// This notifies the current configuration of a particular characteristic/descriptor for a
    /// particular peer. It will be called when the peer GATT client changes the configuration.
    ///
    /// The Bluetooth stack maintains the state of each peer's configuration across reconnections.
    /// As such, this method will also be called when a peer connects for each characteristic with
    /// the initial, persisted state of the newly-connected peer's configuration. However, clients
    /// should not rely on this state being persisted indefinitely by the Bluetooth stack.
    ///
    /// + request `peer_id` The PeerId of the GATT client associated with this particular CCC.
    /// + request `handle` The handle of the characteristic associated with the `notify` and
    ///  `indicate` parameters.
    /// + request `notify` True if the client has enabled notifications, false otherwise.
    /// + request `indicate` True if the client has enabled indications, false otherwise.
    /// - response empty Returns nothing to acknowledge the characteristic configuration.
    CharacteristicConfiguration(struct {
        peer_id bt.PeerId;
        handle Handle;
        notify bool;
        indicate bool;
    }) -> ();

    /// Called when a peer requests to read the value of a characteristic or descriptor. It is
    /// guaranteed that the peer satisfies the permssions associated with this attribute.
    ///
    /// + request `peer_id` The PeerId of the GATT client making the read request.
    /// + request `handle` The handle of the requested descriptor/characteristic.
    /// + request `offset` The offset at which to start reading the requested value.
    /// - response `value` The value of the characteristic.
    /// * error See `gatt2.Error` documentation for possible errors.
    ReadValue(struct {
        peer_id bt.PeerId;
        handle Handle;
        offset int32;
    }) -> (struct {
        value bytes:MAX_VALUE_LENGTH;
    }) error Error;

    /// Called when a peer issues a request to write the value of a characteristic or descriptor. It
    /// is guaranteed that the peer satisfies the permissions associated with this attribute.
    ///
    /// + request `peer_id` The PeerId of the GATT client making the write request. Always present.
    /// + request `handle` The handle of the requested descriptor/characteristic. Always present.
    /// + request `offset` The offset at which to start writing the value. If the offset is 0, any
    ///   existing value should be overwritten by the new value. Otherwise, the existing value from
    ///   offset:(offset + len(value)) should be changed to `value`. Always present.
    /// + request `value` The new value for the descriptor/characteristic. Always present, but may
    ///   be the empty string.
    /// - response  The implementation must send an empty response once the value has been updated
    ///   as confirmation.
    /// * error See `gatt2.Error` documentation for possible errors.
    WriteValue(table {
        1: peer_id bt.PeerId;
        2: handle Handle;
        3: offset uint32;
        4: value bytes:MAX_VALUE_LENGTH;
    }) -> (struct {}) error Error;

    /// Called to provide GATT information specific to a peer. PeerUpdate will not be called unless
    /// the prior invocation received a response. As such, the implementation can simply ignore the
    /// first invocation if they are not interested in any PeerUpdate fields.
    ///
    /// A PeerUpdate will be made before propagating any other interaction from the peer to the
    /// LocalService (Write/ReadValue, CharacteristicConfiguration) on a best-effort basis, as long
    /// as all preceding PeerUpdates were acknowledged.
    ///
    /// + request `peer_id` The PeerId the update pertains to. Always present.
    /// + request `mtu` The maximum number of bytes that fit in a notification/indication to this
    ///   peer. Any bytes past this limit are silently truncated. Most clients need not concern
    ///   themselves with this unless they are using notifications/indications for high throughput.
    ///   Optional.
    /// - response An empty response to acknowledge that the update was received.
    PeerUpdate(table {
        1: peer_id bt.PeerId;
        2: mtu uint16;
    }) -> ();

    /// After this event, new peers will no longer be able to discover the service, although peers
    /// which have already discovered this service may still access it. This should be sent once per
    /// service lifetime; sending more than once closes the protocol and disconnects GATT clients.
    @transitional("Not currently supported. Comment on fxbug.dev/98598 to request support")
    -> OnSuppressDiscovery();

    /// This event is used to send a notification to a peer. Notifications should be used instead of
    /// indications when the service does *not* require peer confirmation of the update.
    ///
    /// Notifications should not be sent to peers which have not enabled notifications on a
    /// particular characteristic - if they are sent, they will not be propagated. The Bluetooth
    /// stack will track this configuration for the lifetime of the service.
    ///
    /// LocalServices must keep track of available credit provided by the `ValueChangedCredit`
    /// method and send at most that many `OnNotifyValue` and `OnIndicateValue` events. If more
    /// events are sent than available credits, the protocol will be closed.
    -> OnNotifyValue(ValueChangedParameters);

    /// This event is used to send an indication to a peer. Indications should be used instead of
    /// notifications when the service *does* require peer confirmation of the update.
    ///
    /// Indications should not be sent to peers which have not enabled indications on a particular
    /// characteristic - if they are sent, they will not be propagated. The Bluetooth stack will
    /// track this configuration for the lifetime of the service.
    ///
    /// LocalServices must keep track of available credit provided by the `ValueChangedCredit`
    /// method and send at most that many `OnNotifyValue` and `OnIndicateValue` events. If more
    /// events are sent than available credits, the protocol will be closed.
    ///
    /// + request `update` The parameters associated with the changed characteristic.
    /// + request `confirmation` When all peers that will be updated have confirmed the indication,
    ///   `confirmation` is signalled with ZX_EVENTPAIR_SIGNALLED. `confirmation` will be closed if
    ///   indicating any peer fails, such as if the peer hasn't configured indications, is not
    ///   connected, or does not confirm within the ATT transaction timeout of 30 seconds (Bluetooth
    ///   5.3 Vol. 3 Part F 3.3.3). To track indication confirmation on a per-peer basis, the
    ///   implementation can send this event with a single ID in `update.peer_ids`.
    // `confirmation` is an EventPair instead of an Event because the language bindings for Events
    // treat them as resources/move-only, but the LocalService will need to retain a handle to the
    // `confirmation` kernel object in order to wait on the signal from the other side.
    -> OnIndicateValue(resource struct {
        update ValueChangedParameters;
        confirmation zx.handle:EVENTPAIR;
    });

    /// Add credit for sending indications/notifications. Implementors are defined to start out with
    /// INITIAL_VALUE_CHANGED_CREDITS credits before this method is called. Implementors must keep
    /// track of the available credit they have. The implementor can send exactly one OnNotifyValue
    /// or OnIndicateValue event for each credit. Note that `ValueChangedCredit` will only be called
    /// if at least one indication/notification has been sent since the prior call. 
    ValueChangedCredit(struct {
        additional_credit uint8;
    });
};

@discoverable
protocol Server {
    /// Publishes the given `service` so that it is available to all remote peers. Upon publication,
    /// the service is defined to have INITIAL_VALUE_CHANGED_CREDITS credits available for sending
    /// indications/notifications.
    ///
    /// The caller must assign distinct handles to the characteristics and descriptors listed in
    /// `info`. These identifiers will be used in requests sent to `service`.
    ///
    /// + request `info` Defines the structure of the GATT service. Includes characteristics and
    ///   descriptors that will be made available to peers, as well as the service handle, which is
    ///   required to be unique across all services published to this Server.
    /// + request `service` Provides the implementation of the service per the documented behavior
    ///   of a `LocalService`.
    /// - response An empty response indicates the service was successfully published.
    /// * error See `gatt2.PublishServiceError` for possible failure modes.
    @transitional("Implementation and migration progress tracked in http://fxbug.dev/36375")
    PublishService(resource struct {
        info ServiceInfo;
        service client_end:LocalService;
    }) -> (struct {}) error PublishServiceError;
};
