blob: 0932453a7d50ed2178ed7bac5edd98a741aadf06 [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.virtualaudio;
using zx;
const MAX_UI_STRING_SIZE uint32 = 256;
const MAX_FORMAT_RANGES uint32 = 64;
const CONTROL_NODE_NAME string = "/dev/sys/platform/00:00:2f/virtual_audio";
/// This protocol provides methods for adding and removing virtual audio
/// devices. This protocol is made available through the device tree via
/// `CONTROL_NODE_NAME`.
protocol Control {
/// Adds an input device to the device tree.
/// The device lives until the `Device` FIDL channel is closed.
AddInput(resource struct {
config Configuration;
server server_end:Device;
}) -> (struct {}) error Error;
/// Adds an output device to the device tree.
/// The device lives until the `Device` FIDL channel is closed.
AddOutput(resource struct {
config Configuration;
server server_end:Device;
}) -> (struct {}) error Error;
/// Returns the number of active input and output virtual devices.
GetNumDevices() -> (struct {
num_input_devices uint32;
num_output_devices uint32;
});
/// Synchronously remove all all active input and output devices.
RemoveAll() -> ();
};
/// Configures a virtual audio device.
type Configuration = table {
/// Device's name.
/// If not specified, a default name is used.
1: device_name string:MAX_UI_STRING_SIZE;
/// Device manufacturor's name.
/// If not specified, a default manufacturer name is used.
2: manufacturer_name string:MAX_UI_STRING_SIZE;
/// Device product's.
/// If not specified, a default product name is used.
3: product_name string:MAX_UI_STRING_SIZE;
/// Device's unique identifier, a 16 byte string.
/// If not specified, a default ID is used.
4: unique_id array<uint8, 16>;
/// FIFO depth in bytes.
/// If not specified, defaults to an arbitrary amount.
5: fifo_depth_bytes uint32;
/// External delay.
/// If not specified, defaults to an arbitrary duration.
6: external_delay zx.duration;
/// Supported format ranges for this virtual audio device.
/// If empty, supports only a 48kHz stereo int16 format by default.
7: supported_formats vector<FormatRange>:MAX_FORMAT_RANGES;
/// Configuration for the device's clock.
/// If not specified, use the domain of the monotonic clock.
8: clock_properties ClockProperties;
/// Constraints on the ring buffer.
/// If not specified, there are no constraints.
9: ring_buffer_constraints RingBufferConstraints;
/// Configuration of the device gain.
/// If not specified, the device has unity gain and cannot mute, enable AGC,
/// or change gain.
10: gain_properties GainProperties;
/// Configuration of the device's plug state.
/// If not specified, the device starts plugged in, with plug notifications
/// enabled, and is not hardwired.
11: plug_properties PlugProperties;
/// Initial notification frequency.
/// This can be changed later with SetNotificationFrequency.
12: initial_notifications_per_ring uint32;
};
type FormatRange = struct {
/// Has type audio_sample_format_t (see zircon/device/audio.h)
sample_format_flags uint32;
min_frame_rate uint32;
max_frame_rate uint32;
min_channels uint8;
max_channels uint8;
/// Bitfield of `ASF_RANGE_FLAG_FPS_*` flags (see zircon/device/audio.h)
rate_family_flags uint16;
};
type ClockProperties = struct {
/// The clock domain is an int32 provided by the clock tree to an audio
/// driver. special values for CLOCK_DOMAIN_MONOTONIC (0), and
/// CLOCK_DOMAIN_EXTERNAL (-1) (not locally controllable) are defined in
/// `fuchsia.hardware.audio`. Other than -1, any negative value
/// for clock_domain is invalid and will be ignored.
domain int32;
/// Initial rate-adjustment value for this clock. May be non-zero only if
/// `clock_domain != 0`.
initial_rate_adjustment_ppm int32;
};
/// Set restrictions for the device ring buffer. This must be called before
/// calling `Add()`, or after `Remove()`. Once the device is activated, the
/// ring buffer and its size are returned by the driver in response to an
/// `AUDIO_RB_CMD_GET_BUFFER` command on the ring buffer channel.
/// Note: both min_frames and max_frames must be multiples of modulo_frames.
type RingBufferConstraints = struct {
/// The ring buffer must have at least this many frames.
/// Must be a multiple of `modulo_frames`.
min_frames uint32;
/// The ring buffer can have at most this many frames.
/// Must be a multiple of `modulo_frames`.
max_frames uint32;
/// The ring buffer must have a multiple of this many frames.
/// Cannot be zero.
modulo_frames uint32;
};
type GainProperties = struct {
min_gain_db float32;
max_gain_db float32;
gain_step_db float32;
current_gain_db float32;
can_mute bool;
current_mute bool;
can_agc bool;
current_agc bool;
};
type PlugProperties = struct {
plug_change_time zx.time;
plugged bool;
hardwired bool;
can_notify bool;
};
/// This protocol represents the base functionality of active audio devices. A
/// device is active until this protocol is closed, at which point the device is
/// automatically removed.
protocol Device {
/// Returns the format selected by the client, or `NO_RING_BUFFER` if the
/// client has not yet selected a ring buffer format.
GetFormat() -> (struct {
frames_per_second uint32;
sample_format uint32;
num_channels uint32;
external_delay zx.duration;
}) error Error;
/// Notifies all subscribed listeners when the above format is set or changed.
-> OnSetFormat(struct {
frames_per_second uint32;
sample_format uint32;
num_channels uint32;
external_delay zx.duration;
});
/// Returns the current gain state for this device.
GetGain() -> (struct {
current_mute bool;
current_agc bool;
current_gain_db float32;
});
/// Notifies all subscribed listeners when the above gain is set or changed.
-> OnSetGain(struct {
current_mute bool;
current_agc bool;
current_gain_db float32;
});
/// Returns details about the ring buffer. Returns `NO_RING_BUFFER` if the
/// client has not yet created the ring buffer.
GetBuffer() -> (resource struct {
ring_buffer zx.handle:VMO;
num_ring_buffer_frames uint32;
notifications_per_ring uint32;
}) error Error;
/// Notifies all subscribed listeners when the above buffer has been
/// created.
-> OnBufferCreated(resource struct {
ring_buffer zx.handle:VMO;
num_ring_buffer_frames uint32;
notifications_per_ring uint32;
});
/// Overrides the position notification frequency for this stream.
/// This affects the frequency of `OnPositionNotify` events only. It does
/// not affect the frequency of notification events sent through the audio
/// driver APIs.
SetNotificationFrequency(struct {
notifications_per_ring uint32;
});
/// Notifies all subscribed listeners when the device is commanded to Start
/// streaming. This can only occur after a device is fully configured
/// (format is set; ring buffer is established and fetched).
-> OnStart(struct {
start_time zx.time;
});
/// Notifies all subscribed listeners when the device is commanded to Stop
/// streaming. This can only occur when the device is already Started. Stop
/// returns the device to a fully-configured state. Upon this command, the
/// already-set format and ring buffer are retained without change, but
/// position will re-begin at 0, if the device is again Started.
-> OnStop(struct {
stop_time zx.time;
ring_position uint32;
});
/// Returns the current position (in bytes) within the ring buffer, along
/// with the time (per MONOTONIC clock) that corresponds with that position.
/// This can only be called after the ring buffer is established. Returns
/// `NOT_STARTED` if the device has not yet Started streaming.
GetPosition() -> (struct {
monotonic_time zx.time;
ring_position uint32; // position in bytes
}) error Error;
/// Notifies all subscribed listeners when any position notification is
/// issued by the driver. The frequency of these per-stream notifications is
/// set by whoever opened the device,, though the frequency can be overriden
/// by `SetNotificationFrequency`.
-> OnPositionNotify(struct {
monotonic_time zx.time;
ring_position uint32; // position in bytes
});
/// Hot-plugs or hot-unplugs an active virtual device, at the specified
/// time.
ChangePlugState(struct {
plug_change_time zx.time;
plugged bool;
});
/// Immediately change the virtual device's clock rate, as expressed in the
/// timing and content of position notifications the driver emits.
/// 'ppm_monotonic' cannot exceed [-1000,+1000]. Each rate change in rate is
/// standalone; i.e. successive rate changes are not cumulative.
AdjustClockRate(struct {
ppm_from_monotonic int32;
});
};
type Error = flexible enum {
/// Unknown internal error occurred.
INTERNAL = 1;
/// The ring buffer has not been created yet.
NO_RING_BUFFER = 2;
/// The device has not yet started streaming.
NOT_STARTED = 3;
};