blob: 9e79a7cf03614c914e23ba6b1206154f85c9bd4c [file] [log] [blame]
// Copyright 2019 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.hardware.audio;
using zx;
const UNIQUE_ID_SIZE uint32 = 16;
const MAX_UI_STRING_SIZE uint32 = 256;
const MAX_COUNT_CHANNELS_IN_RING_BUFFER uint32 = 64;
const MAX_COUNT_CHANNELS_TO_USE uint32 = 64;
const MAX_COUNT_SUPPORTED_NUMBER_OF_CHANNELS uint32 = 64;
const MAX_COUNT_CHANNEL_SETS uint32 = 64;
const MAX_COUNT_SUPPORTED_SAMPLE_FORMATS uint32 = 3;
const MAX_COUNT_SUPPORTED_RATES uint32 = 64;
const MAX_COUNT_SUPPORTED_BYTES_PER_SAMPLE uint32 = 8;
const MAX_COUNT_SUPPORTED_VALID_BITS_PER_SAMPLE uint32 = 8;
const MAX_COUNT_FORMATS uint32 = 64;
alias clock_domain = uint32;
const CLOCK_DOMAIN_MONOTONIC clock_domain = 0x00000000;
const CLOCK_DOMAIN_EXTERNAL clock_domain = 0xFFFFFFFF;
type SampleFormat = strict enum : uint8 {
/// Signed Linear Pulse Code Modulation samples at the host endianness.
PCM_SIGNED = 1;
/// Unsigned Linear Pulse Code Modulation samples at the host endianness.
PCM_UNSIGNED = 2;
/// Floating point samples IEEE-754 encoded.
PCM_FLOAT = 3;
};
type ChannelAttributes = table {
/// Minimum frequency guaranteed to be emitted by (or captured in) this channel, in Hz. Optional.
/// If both `min_frequency` and `max_frequency` are not included, then this channel is assumed
/// to cover the full frequency range of this device.
/// TODO(fxbug.dev/81743): Define expectations beyond these min/max limits and enable drivers
/// to express tolerances related to this.
1: min_frequency uint32;
/// Maximum frequency guaranteed to be emitted by (or captured in) this channel, in Hz. Optional.
/// If both `min_frequency` and `max_frequency` are not included, then this channel is assumed
/// to cover the full frequency range of this device.
/// TODO(fxbug.dev/81743): Define expectations beyond these min/max limits and enable drivers
/// to express tolerances related to this.
2: max_frequency uint32;
};
type ChannelSet = table {
/// Describes attributes for this channel set. Required.
/// The size of this vector defines the number of channels supported by this `ChannelSet`.
/// Each element of the vector defines attributes of a single channel.
1: attributes vector<ChannelAttributes>:MAX_COUNT_CHANNELS_IN_RING_BUFFER;
};
type SupportedFormats = table {
/// Supported formats for non-compressed PCM samples with attributes. Required.
1: pcm_supported_formats PcmSupportedFormats;
};
/// Format supporting non-compressed PCM audio. Frames are made up of number of channels samples
/// which have `valid_bits_per_sample` bits of left-justified data within `bytes_per_sample`
/// bytes. All values listed in each vector are supported. When not all combinations supported by
/// the driver can be described with one `SupportedFormats` (and hence one `PcmSupportedFormats`),
/// `GetSupportedFormats` returns more than one `SupportedFormats` in the returned vector.
/// For more detailed information see [Audio Driver Streaming Interface](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_streaming).
type PcmSupportedFormats = table {
/// Vector of possible `ChannelSets` supported. Required.
/// A `ChannelSet` defines a number of channels supported plus a number of optional
/// attributes for these channels.
/// Only one `ChannelSet` is allowed for each unique number of channels.
1: channel_sets vector<ChannelSet>:MAX_COUNT_CHANNEL_SETS;
/// Vector of possible `SampleFormat`s supported. Required.
2: sample_formats vector<SampleFormat>:MAX_COUNT_SUPPORTED_SAMPLE_FORMATS;
/// Vector of possible number of bits allocated to hold a sample,
/// equal or bigger than the actual sample size in `valid_bits_per_sample` in ascending order.
/// Required.
3: bytes_per_sample vector<uint8>:MAX_COUNT_SUPPORTED_BYTES_PER_SAMPLE;
/// Vector of possible number of bits in a sample in ascending order, must be equal or smaller
/// than `bytes_per_channel` for samples to fit. If smaller, bits are left justified, and any
/// additional bits will be ignored. Required.
4: valid_bits_per_sample vector<uint8>:MAX_COUNT_SUPPORTED_VALID_BITS_PER_SAMPLE;
/// Vector of possible frame rates supported in ascending order. Required.
5: frame_rates vector<uint32>:MAX_COUNT_SUPPORTED_RATES;
};
type Format = table {
/// Format supporting non-compressed PCM samples. Required.
1: pcm_format PcmFormat;
};
/// Format supporting non-compressed PCM audio. Frames are made up of `number_of_channels` samples
/// which have `valid_bits_per_sample` bits of left-justified data within `bytes_per_channel`.
/// bytes. For more detailed information see
/// [Audio Driver Streaming Interface](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_streaming).
type PcmFormat = struct {
/// Number of channels.
number_of_channels uint8;
/// Which channels to use as a bitmask. Channels not set in the bitmask are ignored.
/// The least significant bit corresponds to index 0.
channels_to_use_bitmask uint64;
/// The format of all samples.
sample_format SampleFormat;
/// Bytes allocated to hold a sample, equal or bigger than the valid sample size in
/// `valid_bits_per_sample`.
bytes_per_sample uint8;
/// Number of valid bits in a sample, must be equal or smaller than bits in `bytes_per_sample`.
/// If smaller, bits are left justified, and any additional bits must be ignored by the
/// receiver.
valid_bits_per_sample uint8;
/// The frame rate for all samples.
frame_rate uint32;
};
/// Gain state requested by the client or returned by the driver.
type GainState = table {
/// Current mute state. If not included, the state is unmuted.
1: muted bool;
/// Current Automatic Gain Control (AGC) state. If not included, AGC is disabled.
2: agc_enabled bool;
/// Current gain in decibels. Required.
3: gain_db float32;
};
/// Plug state as returned by the driver.
type PlugState = table {
/// Stream is currently plugged in. Required
1: plugged bool;
/// Timestamps the information provided in the rest of the fields of this struct. Required.
2: plug_state_time zx.time;
};
type PlugDetectCapabilities = strict enum {
/// Stream is hardwired (will always be plugged in).
HARDWIRED = 0;
/// Stream is able to asynchronously notify of plug state changes.
CAN_ASYNC_NOTIFY = 1;
};
type StreamProperties = table {
/// A unique identifier. If not included, there is no unique id for the StreamConfig.
1: unique_id array<uint8, UNIQUE_ID_SIZE>;
/// Stream type is input or output. Required.
2: is_input bool;
/// Gain mute capability. If not included, the StreamConfig can't mute.
3: can_mute bool;
/// Automatic Gain Control (AGC) capability. If not included, the StreamConfig can't AGC.
4: can_agc bool;
/// Minimum gain in decibels. Required.
5: min_gain_db float32;
/// Maximum gain in decibels. Required.
6: max_gain_db float32;
/// Gain step in decibels, this value must not be negative, but may be zero to convey an
/// effectively continuous range of values. Must not exceed `max_gain_db` - `min_gain_db`.
/// Required.
7: gain_step_db float32;
/// Plug Detect Capabilities. Required.
8: plug_detect_capabilities PlugDetectCapabilities;
/// UI string for the manufacturer name. If not included, the manufacturer is unspecified.
9: manufacturer string:MAX_UI_STRING_SIZE;
/// UI string for the product name. If not included, the product name is unspecified.
10: product string:MAX_UI_STRING_SIZE;
/// An identifier for the clock domain in which this hardware operates. If the hardware is
/// operating in CLOCK_DOMAIN_MONOTONIC, its nominal rate is locked to that of the
/// ZX_CLOCK_MONOTONIC time reference. Given the start time, and a nominal rate, the position
/// of the playback/capture pointer may always be calculated using a clock monotonic timestamp
/// as the pointer's movement is locked to that of ZX_CLOCK_MONOTONIC.
///
/// Other values indicate that playback/capture is not locked to ZX_CLOCK_MONOTONIC, and moves
/// at its own rate depending on a number of factors. Client will need to make use of the
/// timing information present in the position notification updates in order to recover the
/// clock of the audio stream. The clock_domain comes from an system wide entity (or instance a
/// platform bus or clock tree/global driver). Audio drivers retrieve clock_domain from such
/// system wide entity. Required.
11: clock_domain clock_domain;
};
/// For an overview see
/// [Audio Driver Streaming Interface](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_streaming)
protocol StreamConfig {
/// Allows providing driver health state.
compose Health;
/// Retrieves top level static properties.
GetProperties() -> (struct {
properties StreamProperties;
});
/// Gets formats supported by a given driver. When not all combinations supported by the
/// driver can be described with one `SupportedFormats`, the driver returns more than one
/// `SupportedFormats` in the returned vector. For example, if one `SupportedFormats` allows
/// for 32 bits samples at 48KHz, and 16 bits samples at 96KHz, but not 32 bits samples at
/// 96KHz, then the driver replies with 2 `SupportedFormats`: <<32bits>,<48KHz>> and
/// <<16bits>,<96KHz>>. For simplicity, this example ignores parameters other than rate and
/// bits per sample. In the case where the driver supports either 16 or 32 bits samples at
/// either 48 or 96KHz, the driver would reply with 1 `SupportedFormats`:
/// <<16bits,32bits>,<48KHz,96KHz>>.
GetSupportedFormats() -> (struct {
supported_formats vector<SupportedFormats>:MAX_COUNT_FORMATS;
});
/// `CreateRingBuffer` is sent by clients to select a stream format based on information that
/// the driver provides in `GetSupportedFormats` what is supported by the client, and any other
/// requirement. The `ring_buffer` channel is used to control the audio buffer, if a previous
/// ring buffer channel had been established and was still active, the driver must close that
/// (ring buffer) channel and make every attempt to gracefully quiesce any on-going streaming
/// operations in the process.
CreateRingBuffer(resource struct {
format Format;
ring_buffer server_end:RingBuffer;
});
/// Get the gain state via a hanging get. The driver will reply to the first `WatchGainState`
/// sent by the client and this reply must include a `gain_db` set to 0dB or lower. The driver
/// will not respond to subsequent client `WatchGainState` calls until the gain state changes
/// from what was most recently reported.
WatchGainState() -> (struct {
gain_state GainState;
});
/// Client update of the gain state.
SetGain(struct {
target_state GainState;
});
/// Get the plug detect state via a hanging get. The driver will reply to the first
/// `WatchPlugState` sent by the client. The driver will not respond to subsequent client
/// `WatchPlugState` calls until the plug state changes from what was most recently reported.
WatchPlugState() -> (struct {
plug_state PlugState;
});
};