audio_ctrl.c revision 88447a05f537aabe9a1bc3d5313f22581ec992a7
/*
* 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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/sysmacros.h>
#include "audio_impl.h"
/*
* Audio Control functions.
*/
/*
* Given a control structure - free all names
* strings allocated to it.
*
* ctrl - The control who's names that will be free'd.
*/
static void
{
int indx;
}
}
}
/*
* This will allocate and register a control for my audio device.
*
* d - The audio device the control will be attached to.
* desc - Attributes about this new control
* read_fn - Callback function in driver to read control
* write_fn - Callback function in driver to write control.
*
* On success this will return a control structure else NULL.
*
* The value passed in for a control number in the audio_ctrl_desc_t
* has some special meaning. If it is less then AUDIO_CONTROL_EXTBASE
* then the control is assumed to be a known control. If it is
* AUDIO_CONTROL_EXTBASE then the framework will allocate a unique
* control number and replace it in the audio_ctrl_desc_t structure
* and this control is considered an extended driver private control.
* The number that is replaced in audio_ctrl_desc_t will be greater
* then AUDIO_CONTROL_EXTBASE.
*
*/
{
char scratch[16];
const char *name;
/* Verify arguments */
ASSERT(d);
/* We cannot deal with unnamed controls */
return (NULL);
}
/*
* If this was called with a control name that was already
* added, then we do some special things. First we reuse the
* control audio_ctrl_t and as far as outside users are
* concerned the handle is reused. To users this looks like we
* are changing the controls attributes. But what we really do
* is free every thing allocated to the control and then
* reinit everything. That way the same code can get used for
* both.
*
* We verify anything that could fail before we change the
* control or commit to any changes. If there is something bad
* return null to indicate an error but the original control
* is still usable and untouched.
*/
/* Allocate a new control */
} else {
/* Re-configure an existing control */
case AUDIO_CTRL_TYPE_BOOLEAN:
case AUDIO_CTRL_TYPE_STEREO:
case AUDIO_CTRL_TYPE_MONO:
case AUDIO_CTRL_TYPE_METER:
case AUDIO_CTRL_TYPE_ENUM:
break;
default:
audio_dev_warn(d, "bad control type %d for %s "
return (NULL);
}
/*
* By removing it from the list we prevent the need to lock
* and check for locks on the control itself.
* Also by doing this we can use the normal add code to do
* what it normally does below.
*/
rw_exit(&d->d_ctrl_lock);
}
/* Fill in new control description */
/* Process type of control special actions, if any */
case AUDIO_CTRL_TYPE_BOOLEAN:
case AUDIO_CTRL_TYPE_STEREO:
case AUDIO_CTRL_TYPE_MONO:
case AUDIO_CTRL_TYPE_METER:
break;
case AUDIO_CTRL_TYPE_ENUM:
continue;
"bit%d", bit);
}
}
break;
default:
audio_dev_warn(d, "bad control type %d for %s",
goto ctrl_fail;
}
}
}
rw_exit(&d->d_ctrl_lock);
return (ctrl);
if (ctrl) {
}
return (NULL);
}
/*
* This will remove a control from my audio device.
*
* ctrl - The control will be removed.
*/
void
{
audio_dev_t *d;
/* Verify argument */
ASSERT(d);
rw_exit(&d->d_ctrl_lock);
}
static int
{
audio_dev_t *d = arg;
audio_client_t *c;
if (val > 100) {
return (EINVAL);
}
}
rw_exit(&d->d_clnt_lock);
return (0);
}
static int
{
audio_dev_t *d = arg;
return (0);
}
int
{
if (d->d_pcmvol_ctrl == NULL) {
desc.acd_minvalue = 0;
d->d_pcmvol = 75;
}
return (0);
}
/*
* This will notify clients of need to reread control
* values since they have changed.
*
* There will be a routine that allows a client to register
* a callback. All callbacks registered to this device should
* get called from this routine.
*
* d - The device that needs updates.
*/
void
{
}
/*
* 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
{
int ret;
/* Verify arguments */
return (ENXIO);
}
return (ret);
}
return (ret);
}
/*
* 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
{
int ret;
/* Verify arguments */
ASSERT(d);
return (ENXIO);
}
if (ret == 0)
return (ret);
}