// Copyright 2020 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.bredr;

using fuchsia.hardware.audio;
using fuchsia.bluetooth;

type ScoErrorCode = strict enum {
    FAILURE = 1;
    CANCELLED = 2;
    INVALID_ARGUMENTS = 3;
    PARAMETERS_REJECTED = 4;
};

/// Codec parameter sets defined in the Hands-Free Profile specification (v1.8, section 5.7).
type HfpParameterSet = strict enum : uint8 {
    T1 = 1;
    T2 = 2;
    S1 = 3;
    S2 = 4;
    S3 = 5;
    S4 = 6;
    D0 = 7;
    D1 = 8;
};

/// Indicates the audio transport that should be used for the data on a synchronous
/// connection.
type DataPath = strict enum : uint8 {
    /// The HCI transport. Data will be sent/received through the ScoConnection protocol.
    HOST = 1;

    /// Transport audio data directly between the controller and the audio hardware.
    /// The ScoConnection protocol will not be used to send/receive data.
    // TODO(https://fxbug.dev/42140527): Document how offloading is configured.
    OFFLOAD = 2;

    /// The audio test mode transport. See Core Spec v5.2, Vol 4, Part E, Section 7.6.2 for details.
    TEST = 3;
};

type ScoConnectionParameters = table {
    /// Set of SCO parameters from the Hands-Free Profile specification.
    /// Required.
    1: parameter_set HfpParameterSet;

    /// The over-the-air coding format used for transmitted and received data.
    /// Required.
    2: air_coding_format fuchsia.bluetooth.AssignedCodingFormat;

    /// Frame size produced by the codec in the context of over-the-air coding.
    /// Required.
    3: air_frame_size uint16;

    /// Host-controller data rate in bytes/second.
    /// Required.
    4: io_bandwidth uint32;

    /// The coding format used over the transport.
    /// Required.
    5: io_coding_format fuchsia.bluetooth.AssignedCodingFormat;

    /// The number of bits in each sample/frame of data.
    /// Required.
    6: io_frame_size uint16;

    /// The data format over the transport for linear samples.
    /// Ignored for non-linear coding formats.
    /// Optional.
    /// SIGNED indicates 2's complement sign encoding.
    /// FLOAT is not supported.
    7: io_pcm_data_format fuchsia.hardware.audio.SampleFormat;

    /// For linear samples, indicates how many bit positions the MSB of the sample is away
    /// from the MSB of the data.
    /// Ignored for non-linear coding formats.
    /// Optional.
    /// Default: 0.
    8: io_pcm_sample_payload_msb_position uint8;

    /// The data transport.
    /// Required.
    9: path DataPath;

    /// Indicates the maximum data buffer size that may be sent.
    /// Optional. Only present after a connection has successfully been connected. Ignored when
    /// requesting a connection.
    10: max_tx_data_size uint16;
};

/// Inbound SCO data has a RxPacketStatus that indicates possible data loss or corruption.
type RxPacketStatus = strict enum : uint8 {
    /// The controller marked all data as "good data".
    CORRECTLY_RECEIVED_DATA = 0x0;
    /// Some of the data may have errors.
    POSSIBLY_INVALID_DATA = 0x1;
    /// All data was lost. The payload will be empty.
    NO_DATA_RECEIVED = 0x2;
    /// Some of the data was lost, and the lost regions of data will be set to 0.
    DATA_PARTIALLY_LOST = 0x3;
};

closed protocol ScoConnection {
    // Read the next inbound SCO payload.
    // Hangs until new data is received.
    // Only one Read request may be pending at a time. Additional requests will result in protocol
    // closure.
    strict Read() -> (struct {
        status_flag RxPacketStatus;
        data vector<uint8>:MAX;
    });

    // Write `data` to the SCO connection.
    // If Write tries to send more data than `max_tx_data_size`, the protocol will be closed.
    // Only one Write request may be pending at a time. Additional requests will result in protocol
    // closure.
    strict Write(struct {
        data vector<uint8>:MAX;
    }) -> ();
};

/// Represents an active synchronous connection request by a profile.
/// Either `Connected()` or `Error()` will be called and then server will close the protocol.
closed protocol ScoConnectionReceiver {
    /// Called upon successful connection establishment.
    /// `params` contains the parameters that were used to establish the connection.
    strict Connected(resource struct {
        connection client_end:ScoConnection;
        params ScoConnectionParameters;
    });

    /// Called when connection establishment fails or is cancelled by the host.
    strict Error(struct {
        error ScoErrorCode;
    });
};
