/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_AUDIO_CLIENT_H
#define	_AUDIO_CLIENT_H

/*
 * Structure implementation in audio_impl.h
 */
#include <sys/audio/audio_common.h>

#define	AUDIO_IOCTL_MAX_INDEX	8
typedef struct audio_ioctl {
	int			a_cmd;
	size_t			a_size[AUDIO_IOCTL_MAX_INDEX];
	void			*a_data[AUDIO_IOCTL_MAX_INDEX];
	int			a_prv_state;
	uint_t			a_model;
} audio_ioctl_t;

typedef struct audio_client_ops {
	const char	*aco_minor_prefix;
	void		*(*aco_dev_init)(audio_dev_t *);
	void		(*aco_dev_fini)(void *);
	int		(*aco_open)(audio_client_t *, int);
	int		(*aco_close)(audio_client_t *);
	void		(*aco_ioctl)(audio_client_t *, audio_ioctl_t *);
	int		(*aco_mmap)(audio_client_t *, ...);
	void		(*aco_drain)(audio_client_t *);
	void		(*aco_output)(audio_client_t *);
	void		(*aco_eof)(audio_client_t *);
	void		(*aco_notify)(audio_client_t *);
} audio_client_ops_t;

void *auclnt_get_private(audio_client_t *);
void auclnt_set_private(audio_client_t *, void *);

const char *auclnt_get_name(audio_client_t *);
const char *auclnt_get_description(audio_client_t *);
const char *auclnt_get_version(audio_client_t *);

queue_t *auclnt_get_wq(audio_client_t *);
queue_t *auclnt_get_rq(audio_client_t *);

int auclnt_ioctl_alloc(audio_ioctl_t *, size_t, int);
void auclnt_ioctl_copyin(audio_ioctl_t *, size_t, void *, int);
void auclnt_ioctl_copyout(audio_ioctl_t *, size_t, void *, int);
void auclnt_ioctl_error(audio_ioctl_t *, int);
void auclnt_ioctl_success(audio_ioctl_t *);
void auclnt_ioctl_finish(audio_client_t *, audio_ioctl_t *);

int auclnt_set_output_rate(audio_client_t *, int);
int auclnt_set_input_rate(audio_client_t *, int);
int auclnt_get_output_rate(audio_client_t *);
int auclnt_get_input_rate(audio_client_t *);

int auclnt_set_output_format(audio_client_t *, int);
int auclnt_set_input_format(audio_client_t *, int);
int auclnt_get_output_format(audio_client_t *);
int auclnt_get_input_format(audio_client_t *);

int auclnt_set_output_channels(audio_client_t *, int);
int auclnt_set_input_channels(audio_client_t *, int);
int auclnt_get_output_channels(audio_client_t *);
int auclnt_get_input_channels(audio_client_t *);

int auclnt_get_hw_output_format(audio_client_t *);
int auclnt_get_hw_input_format(audio_client_t *);

int auclnt_get_hw_output_rate(audio_client_t *);
int auclnt_get_hw_input_rate(audio_client_t *);

int auclnt_get_hw_output_channels(audio_client_t *);
int auclnt_get_hw_input_channels(audio_client_t *);

uint64_t auclnt_get_hw_input_samples(audio_client_t *);
uint64_t auclnt_get_hw_output_samples(audio_client_t *);

int auclnt_set_output_gain(audio_client_t *, uint8_t, uint8_t);
int auclnt_set_input_gain(audio_client_t *, uint8_t, uint8_t);
void auclnt_get_output_gain(audio_client_t *, uint8_t *, uint8_t *);
void auclnt_get_input_gain(audio_client_t *, uint8_t *, uint8_t *);
int auclnt_set_sun_output_gain(audio_client_t *, uint_t, uint8_t);
int auclnt_set_sun_input_gain(audio_client_t *, uint_t, uint8_t);
void auclnt_get_sun_output_gain(audio_client_t *, uint_t *, uint8_t *);
void auclnt_get_sun_input_gain(audio_client_t *, uint_t *, uint8_t *);

int auclnt_set_output_muted(audio_client_t *, boolean_t);
int auclnt_set_input_muted(audio_client_t *, boolean_t);
boolean_t auclnt_get_output_muted(audio_client_t *);
boolean_t auclnt_get_input_muted(audio_client_t *);

uint64_t auclnt_get_output_pos(audio_client_t *);
uint64_t auclnt_get_input_pos(audio_client_t *);

uint64_t auclnt_get_output_samples(audio_client_t *);
uint64_t auclnt_get_input_samples(audio_client_t *);

void auclnt_set_output_samples(audio_client_t *, uint64_t);
void auclnt_set_input_samples(audio_client_t *, uint64_t);

uint64_t auclnt_get_eof(audio_client_t *);
void auclnt_set_eof(audio_client_t *, uint64_t);

void auclnt_start_output(audio_client_t *);
void auclnt_start_input(audio_client_t *);

void auclnt_set_output_paused(audio_client_t *, boolean_t);
void auclnt_set_input_paused(audio_client_t *, boolean_t);
boolean_t auclnt_get_output_paused(audio_client_t *);
boolean_t auclnt_get_input_paused(audio_client_t *);

void auclnt_flush_output(audio_client_t *);

boolean_t auclnt_pending_output(audio_client_t *);

unsigned auclnt_get_capab(audio_client_t *);
#define	AUDIO_CLIENT_CAP_PLAY		(1U << 0)
#define	AUDIO_CLIENT_CAP_RECORD		(1U << 1)
#define	AUDIO_CLIENT_CAP_DUPLEX		(1U << 2)

int auclnt_get_oflag(audio_client_t *);

int auclnt_open(audio_client_t *, unsigned, int);
void auclnt_close(audio_client_t *);

void auclnt_register_ops(minor_t, audio_client_ops_t *);

minor_t	auclnt_get_minor(audio_client_t *);
minor_t auclnt_get_original_minor(audio_client_t *);
minor_t auclnt_get_minor_type(audio_client_t *);

/*
 * Return the process id that performed the original open() of the client.
 */
pid_t auclnt_get_pid(audio_client_t *);

/*
 * Return the command name that performed the original open() of the
 * client.  Note that this may be truncated to 16 characters, but it
 * is canonicalized to the filename of the executable.
 */
const char *auclnt_get_command(audio_client_t *);

/*
 * Return the full process arguments (unparsed).
 */
const char *auclnt_get_psargs(audio_client_t *);

/*
 * Get an opaque handle the underlying device for an audio client.
 */
audio_dev_t *auclnt_get_dev(audio_client_t *);

/*
 * Audio control functions for use by clients.
 */

/*
 * This will walk all controls registered to my device and callback
 * to walker for each one with its audio_ctrl_desc_t..
 *
 * Note that walk_func may return values to continue (AUDIO_WALK_CONTINUE)
 * or stop walk (AUDIO_WALK_STOP).
 *
 */
void auclnt_walk_controls(audio_client_t *,
    int (*walker)(audio_ctrl_t *, void *), void *);

/*
 * This will search all controls attached to a clients
 * audio device for a control with the desired control
 * number.
 *
 * d               - the device for the client making the request
 * ctrlnum         - the control number being looked for.
 *
 * On successful return a ctrl handle will be returned. On
 * failure NULL is returned.
 */
audio_ctrl_t *auclnt_find_control(audio_dev_t *d, uint32_t ctrlnum);

/*
 * Given a known control, get its attributes.
 *
 * The caller must supply a audio_ctrl_desc_t structure.  Also the
 * values in the structure are ignored when making the call and filled
 * in by this function.
 *
 * If an error occurs then a non-zero is returned.
 */
int auclnt_control_describe(audio_ctrl_t *control, audio_ctrl_desc_t *desc);


/*
 * This is used to read the current value of a control.
 * Note, this will cause a callback into the driver to get the value.
 *
 * ctrl        - should be the valid control being read.
 * value       - is a pointer to the place that will contain the value read.
 *
 * On return zero is returned on success else errno is returned.
 *
 */

int auclnt_control_read(audio_ctrl_t *ctrl, uint64_t *value);
/*
 * This is used to write a value to a control.
 * Note, this will cause a callback into the driver to write the value.
 *
 * ctrl        - should be the valid control being written.
 * value       - is value to set the control to.
 *
 * On return zero is returned on success else errno is returned.
 *
 */
int auclnt_control_write(audio_ctrl_t *ctrl, uint64_t value);

/*
 * Walk all the audio devices on the system.  Useful for clients
 * like sndstat, which may need to inquire about every audio device
 * on the system.
 */
void auclnt_walk_devs(int (*walker)(audio_dev_t *, void *), void *arg);

/*
 * Walk all the open client structures for a named audio device.
 * Clients can use this to find "peer" clients accessing the same
 * audio device.  (This is useful for implementing special linkages,
 * e.g. between /dev/audio and /dev/audioctl.)
 */
void auclnt_walk_peers(audio_client_t *,
    int (*walker)(audio_client_t *, void *), void *arg);

audio_client_t *auclnt_hold(audio_dev_t *, int);
void auclnt_release(audio_client_t *);

int auclnt_get_max_clients(audio_client_t *);
int auclnt_get_client_id(audio_client_t *);
uint64_t auclnt_get_unique_id(audio_client_t *);
boolean_t auclnt_is_mixer_app(audio_client_t *);

/*
 * Retrieve minor-specific data for the instance.  This allows for
 * personality modules to store persistent state data on a physical
 * device (e.g. to store persistent settings.)  Synchronization of
 * stored settings between personality modules is up to the
 * personality modules themselves.
 */
void *auclnt_get_dev_data(audio_client_t *);
void *auclnt_get_dev_data_by_minor(audio_client_t *, minor_t);

/*
 * Simpler warning message, alternative to cmn_err.
 */
void auclnt_warn(audio_client_t *, const char *fmt, ...);

#endif	/* _AUDIO_CLIENT_H */
