/*
* 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
*/
/*
*/
#include <sys/sysmacros.h>
#include "audio_client.h"
static const struct {
int oss;
int fmt;
} oss_formats[] = {
{ AFMT_MU_LAW, AUDIO_FORMAT_ULAW },
{ AFMT_A_LAW, AUDIO_FORMAT_ALAW },
{ AFMT_U8, AUDIO_FORMAT_U8 },
{ AFMT_S8, AUDIO_FORMAT_S8 },
{ AFMT_AC3, AUDIO_FORMAT_AC3 },
};
/* common structure shared between both mixer and dsp nodes */
struct ossclient {
/* sndstat */
char *o_ss_buf;
};
struct ossdev {
int d_play_grp;
int d_rec_grp;
int d_mon_grp;
int d_misc_grp;
};
static int
{
int cnt;
cnt++;
return (AUDIO_WALK_CONTINUE);
if (mask & 1) {
cnt++;
}
}
}
return (AUDIO_WALK_CONTINUE);
}
/*
* Add one entry to the OSS user control table to internal control
* helper table.
*
* This is used with auimpl_walk_controls. The table must be pre-
* allocated before it is walk'd. This includes the root and
* extended control markers!
*/
static int
{
int bit;
const char *name;
int parent;
int flags;
unsigned scope;
return (AUDIO_WALK_CONTINUE);
parent = 0;
/*
* Add appropriate group if not already done so.
*/
if (!odev->d_play_grp) {
}
}
}
} else {
if (!odev->d_misc_grp) {
}
}
"%s", name);
}
/* Next available open entry */
/* Record the underlying control handle */
/*
* Now setup the oss entry
*/
/* all controls should be pollable for now */
/*
* The following flags are intended to help out applications
* which need to figure out where to place certain controls.
* A few further words of guidance:
*
* Apps that just want a single master volume control should
* adjust the control(s) that are labelled with MIXF_PCMVOL if
* present. They can fall back to adjusting all MAINVOL
* levels instead, if no PCMVOL is present.
*
* Controls that are one type on a certain device might be a
* different type on another device. For example,
* levels, but lacks a master record gain. AC'97, on the
* other hand, has individual monitor gains for inputs, but
* only a single master recording gain.
*/
flags |= MIXF_READABLE;
flags |= MIXF_WRITEABLE;
flags |= MIXF_CENTIBEL;
flags |= MIXF_DECIBEL;
flags |= MIXF_MAINVOL;
flags |= MIXF_PCMVOL;
flags |= MIXF_RECVOL;
flags |= MIXF_MONVOL;
/*
* For now just use the same extname as the real name.
*/
/*
* Now we deal with various control types.
*/
case AUDIO_CTRL_TYPE_BOOLEAN:
break;
case AUDIO_CTRL_TYPE_STEREO:
break;
case AUDIO_CTRL_TYPE_MONO:
break;
case AUDIO_CTRL_TYPE_ENUM:
/*
* We turn AUDIO_CTRL_FLAG_MULTI into a group
* of checkboxes, since OSS can't represent it
* natively.
*/
bit = 0;
while (mask) {
if (mask & 1) {
}
bit++;
mask >>= 1;
}
return (AUDIO_WALK_CONTINUE);
} else {
/*
* NB: This is sufficient only for controls
* with a single value. It cannot express the
* richer bitmask capabilities.
*/
/*
* For an enumaration, we need to figure out
* which values are present, and set the
* appropriate mask and max value.
*/
bit = 0;
while (mask) {
if (mask & 1) {
}
mask >>= 1;
bit++;
}
}
break;
case AUDIO_CTRL_TYPE_METER:
default:
/* Its an unknown or unsupported (for now) control, skip */
return (AUDIO_WALK_CONTINUE);
}
return (AUDIO_WALK_CONTINUE);
}
/*
* Free up an OSS user land control to internal control,
* helper table.
*/
static void
{
}
/*
* Allocate and fill in an OSS user land controls to internal controls
* helper table. This is done on one audio_dev device.
*/
static void
{
int nctrl = 0;
/* Find out who many entries we need */
nctrl++; /* Needs space for the device root node */
nctrl++; /* Needs space for the device ext marker */
nctrl++; /* Needs space for the play group */
nctrl++; /* Needs space for the record group */
nctrl++; /* Needs space for the monitor group */
nctrl++; /* Needs space for the tone group */
nctrl++; /* Needs space for the 3D group */
nctrl++; /* Needs space for the misc group */
/* Allocate the OSS to boomer helper table */
/*
* Setup special case outputs to output OSS routes helper tables
*/
/*
* Root node is first, that way all others parent is this one
*/
/*
* Root data... nobody should be using this though.
*/
auclnt_get_dev_name(d));
auclnt_get_dev_name(d));
/*
* Insert an extra marker -- needed to keep layout apps hapy.
* This prevents some apps from assuming we are in "LEGACY" mode.
*/
/* Fill in the complete table now */
/* Update the update_counter reference counter for groups */
int i;
ext->update_counter++;
}
}
}
static int
{
int rv;
isp = auclnt_input_stream(c);
osp = auclnt_output_stream(c);
/* note that OSS always uses nonblocking open() semantics */
return (rv);
}
auclnt_close(c);
return (ENOMEM);
}
auclnt_set_private(c, sc);
/* set a couple of common fields */
/* set all default parameters */
goto failed;
}
/* default to 5 fragments to provide reasonable latency */
}
goto failed;
}
/* default to 5 fragments to provide reasonable latency */
}
return (0);
auclnt_close(c);
return (rv);
}
static void
{
sc = auclnt_get_private(c);
if (ddi_can_receive_sig() || (ddi_get_pid() == 0)) {
(void) auclnt_drain(c);
}
auclnt_close(c);
}
/*
* This is used to generate an array of names for an enumeration
*/
static ushort_t
{
uint32_t n;
/* Get current entry to fill in */
"%s", name);
/* Adjust everything for next entry */
return (nxt);
}
/*
* The following two functions are used to count the number of devices
* in under the boomer framework.
*
* We actually report the highest "index", and then if an audio device
* is not found, we report a bogus removed device for it in the actual
* ioctls. This goofiness is required to make the OSS API happy.
*/
int
{
int cnt;
int index;
index = auclnt_get_dev_index(d);
}
return (AUDIO_WALK_CONTINUE);
}
static int
oss_cnt_devs(void)
{
int cnt = 0;
return (cnt);
}
static int
{
int rate;
int oflag;
oflag = auclnt_get_oflag(c);
}
}
return (0);
}
static int
{
int fmt;
int i;
int oflag;
oflag = auclnt_get_oflag(c);
if (*fmtp != AFMT_QUERY) {
/* convert from OSS */
break;
}
}
if (fmt == AUDIO_FORMAT_NONE) {
/* if format not known, return */
goto done;
}
}
}
}
done:
}
/* convert back to OSS */
*(int *)fmtp = AFMT_QUERY;
}
}
return (0);
}
static int
{
/*
* For now, we support all the standard ones. Later we might
* add in conditional support for AC3.
*/
return (0);
}
static int
{
int nchan;
int oflag;
oflag = auclnt_get_oflag(c);
if (nchan != 0) {
(void) auclnt_set_channels(auclnt_output_stream(c),
nchan);
}
(void) auclnt_set_channels(auclnt_input_stream(c),
nchan);
}
}
}
return (0);
}
static int
{
int nchan;
switch (*onoff) {
case 0:
nchan = 1;
break;
case 1:
nchan = 2;
break;
default:
return (EINVAL);
}
return (sndctl_dsp_channels(c, &nchan));
}
static int
{
if (auclnt_get_oflag(c) & FWRITE) {
}
return (0);
}
static int
{
int ncaps;
int osscaps = 0;
if (ncaps & AUDIO_CLIENT_CAP_PLAY)
if (ncaps & AUDIO_CLIENT_CAP_RECORD)
osscaps |= PCM_CAP_INPUT;
if (ncaps & AUDIO_CLIENT_CAP_DUPLEX)
if (osscaps != 0) {
if (!(ncaps & AUDIO_CLIENT_CAP_OPAQUE)) {
}
} else {
/* This is the sndstat device! */
}
return (0);
}
static int
{
int triggers = 0;
int oflag;
oflag = auclnt_get_oflag(c);
if (!auclnt_is_paused(auclnt_output_stream(c))) {
}
}
if (!auclnt_is_paused(auclnt_input_stream(c))) {
}
}
return (0);
}
static int
{
int triggers;
int oflag;
oflag = auclnt_get_oflag(c);
sp = auclnt_output_stream(c);
}
sp = auclnt_input_stream(c);
}
return (0);
}
struct oss_legacy_volume {
};
static int
{
}
}
}
return (AUDIO_WALK_CONTINUE);
}
static void
{
}
static int
{
int vol;
/* convert monophonic soft value to OSS stereo value */
return (0);
}
static int
{
if (vol > 100) {
return (EINVAL);
}
return (0);
}
static int
{
int vol;
return (0);
}
static int
{
if (vol > 100) {
return (EINVAL);
}
return (0);
}
static int
{
if (vol > 100) {
return (EINVAL);
}
return (0);
}
static int
{
if (vol > 100) {
return (EINVAL);
}
return (0);
}
static int
{
/* SPDIF: need to add support with spdif */
return (ENOTSUP);
}
static int
{
/* SPDIF: need to add support with spdif */
return (ENOTSUP);
}
static int
{
/* We are *always* in cooked mode -- at least until we have AC3. */
if (*rvp == 0) {
return (ENOTSUP);
} else {
return (0);
}
}
static int
{
if (auclnt_get_oflag(c) & FWRITE) {
}
return (0);
}
static int
{
if (auclnt_get_oflag(c) & FWRITE) {
}
return (0);
}
static int
{
if (auclnt_get_oflag(c) & FREAD) {
}
return (0);
}
static int
{
if (auclnt_get_oflag(c) & FWRITE) {
}
return (0);
}
static int
{
(void) sndctl_dsp_halt_input(c);
(void) sndctl_dsp_halt_output(c);
return (0);
}
static int
{
return (auclnt_drain(c));
}
static int
{
int bufsz;
int nfrags;
int fragsz;
/* use infinite setting... no change */
return (0);
}
if (fragsz > 16) {
/* basically too big, so, no change */
return (0);
}
/*
* Now we have our desired buffer size, but we have to
* make sure we have a whole number of fragments >= 2, and
* less than the maximum.
*/
if (bufsz >= 65536) {
return (0);
}
/*
* We set the latency hints in terms of bytes, not fragments.
*/
/*
* According to the OSS API documentation, the values provided
* are nothing more than a "hint" and not to be relied upon
* anyway. And we aren't obligated to report the actual
* values back!
*/
return (0);
}
static int
{
}
return (0);
}
/*
* A word about recsrc, and playtgt ioctls: We don't allow ordinary DSP
* applications to change port configurations, because these could have a
* bad effect for other applications. Instead, these settings have to
* be changed using the master mixer panel. In order to make applications
*/
static int
{
return (0);
}
static int
{
*srcp = 0;
return (0);
}
static int
{
*srcp = 0;
return (0);
}
static int
{
return (0);
}
static int
{
*tgtp = 0;
return (0);
}
static int
{
*tgtp = 0;
return (0);
}
static int
{
return (0);
}
static int
{
audio_dev_t *d;
void *iter;
const char *info;
int n;
d = auclnt_get_dev(c);
n = auclnt_get_dev_index(d);
} else {
d = auclnt_hold_dev_by_index(n);
}
if (d == NULL) {
/*
* If device removed (e.g. for DR), then
* report a bogus removed entry.
*/
"<removed>");
"<removed>");
return (0);
}
"%s", auclnt_get_dev_name(d));
"%s (%s)", auclnt_get_dev_description(d),
}
/*
* We don't report interrupt counts, ack counts (which are
* just "read" interrupts, not spurious), or any other flags.
* Nothing should be using any of this data anyway ... these
* values were intended for 4Front's debugging purposes. In
* Solaris, drivers should use interrupt kstats to report
* interrupt related statistics.
*/
if (release)
return (0);
}
static int
{
fmt = auclnt_engine_get_format(e);
rate = auclnt_engine_get_rate(e);
cap = auclnt_engine_get_capab(e);
if (cap & AUDIO_CLIENT_CAP_PLAY) {
}
if (cap & AUDIO_CLIENT_CAP_RECORD) {
}
break;
}
}
return (AUDIO_WALK_CONTINUE);
}
static int
{
audio_dev_t *d;
const char *name;
int n;
unsigned cap;
d = auclnt_get_dev(c);
n = auclnt_get_dev_index(d);
} else {
n++; /* skip pseudo device */
d = auclnt_hold_dev_by_index(n);
}
if (d == NULL) {
/* if device not present, forge a false entry */
si->card_number = n;
return (0);
}
name = auclnt_get_dev_name(d);
cap = auclnt_get_dev_capab(d);
if (cap & AUDIO_CLIENT_CAP_DUPLEX) {
}
if (cap & AUDIO_CLIENT_CAP_PLAY) {
}
if (cap & AUDIO_CLIENT_CAP_RECORD) {
}
/* MMAP: we add PCM_CAP_MMAP when we we support it */
/* we can convert and mix PCM formats */
if (!(cap & AUDIO_CLIENT_CAP_OPAQUE)) {
}
} else {
}
si->card_number = n;
if (release)
return (0);
}
static int
{
audio_dev_t *d;
const char *name;
d = auclnt_get_dev(c);
name = auclnt_get_dev_name(d);
mi->port_number = 0;
return (0);
}
static int
{
return (0);
}
static int
{
*recmask = 0;
return (0);
}
static int
{
*recsrc = 0;
return (0);
}
static int
{
/* single recording source... sort of */
return (0);
}
static int
{
audio_dev_t *d;
const char *name;
int n;
d = auclnt_get_dev(c);
n = auclnt_get_dev_index(d);
} else {
n++;
d = auclnt_hold_dev_by_index(n);
}
if (d == NULL) {
mi->card_number = n;
return (0);
}
if (release)
return (EINVAL);
}
name = auclnt_get_dev_name(d);
if (mi->legacy_device >= 0) {
} else {
/* special nodes use generic sndstat node */
}
if (release)
return (0);
}
static int
{
return (0);
}
static int
{
unsigned n;
if ((auclnt_get_oflag(c) & FWRITE) == 0) {
return (EACCES);
}
sp = auclnt_output_stream(c);
return (0);
}
static int
{
unsigned n;
if ((auclnt_get_oflag(c) & FREAD) == 0) {
return (EACCES);
}
sp = auclnt_input_stream(c);
n = auclnt_get_count(sp);
return (0);
}
static int
{
unsigned framesz;
if (auclnt_get_oflag(c) & FWRITE) {
} else {
*bytes = 0;
}
return (0);
}
static int
{
if (auclnt_get_oflag(c) & FREAD) {
} else {
count->fifo_samples = 0;
}
return (0);
}
static int
{
if (auclnt_get_oflag(c) & FWRITE) {
} else {
count->fifo_samples = 0;
}
return (0);
}
static int
{
unsigned framesz;
unsigned fragsz;
if ((auclnt_get_oflag(c) & FWRITE) == 0) {
return (0);
}
sp = auclnt_output_stream(c);
auclnt_set_samples(sp, 0);
return (0);
}
static int
{
unsigned framesz;
unsigned fragsz;
if ((auclnt_get_oflag(c) & FREAD) == 0) {
return (0);
}
sp = auclnt_input_stream(c);
auclnt_set_samples(sp, 0);
return (0);
}
static int
{
unsigned fragsz;
/*
* Note: The use of this structure is unsafe... different
* meanings for error codes are used by different implementations,
* according to the spec. (Even different versions of the same
* implementation could have different values.)
*
* Rather than try to come up with a reliable solution here, we
* don't use it. If you want to report errors, or see the result
* of errors, use syslog.
*/
sp = auclnt_output_stream(c);
fragsz);
auclnt_set_errors(sp, 0);
sp = auclnt_input_stream(c);
fragsz);
auclnt_set_errors(sp, 0);
return (0);
}
static int
{
int rv;
return (rv);
}
dev = auclnt_get_dev(c);
return (0);
}
static int
{
*versp = OSS_VERSION;
return (0);
}
static int
int *rvalp)
{
int sz;
void *data;
int rv = 0;
return (ENOMEM);
}
} else {
sz = 0;
}
goto done;
}
}
switch (cmd) {
/*
* DSP specific ioctls
*/
case SNDCTL_DSP_HALT:
rv = sndctl_dsp_halt(c);
break;
case SNDCTL_DSP_SYNC:
rv = sndctl_dsp_sync(c);
break;
case SNDCTL_DSP_SPEED:
break;
case SNDCTL_DSP_SETFMT:
break;
case SNDCTL_DSP_GETFMTS:
break;
case SNDCTL_DSP_STEREO:
break;
case SNDCTL_DSP_CHANNELS:
break;
case SNDCTL_DSP_POST:
rv = sndctl_dsp_post(c);
break;
case SNDCTL_DSP_GETCAPS:
break;
case SNDCTL_DSP_GETTRIGGER:
break;
case SNDCTL_DSP_SETTRIGGER:
break;
case SNDCTL_DSP_GETPLAYVOL:
case SOUND_MIXER_READ_VOLUME: /* legacy mixer on dsp */
case SOUND_MIXER_READ_PCM: /* legacy mixer on dsp */
case SOUND_MIXER_READ_OGAIN: /* legacy mixer on dsp */
break;
case SOUND_MIXER_WRITE_VOLUME: /* legacy mixer on dsp */
case SOUND_MIXER_WRITE_PCM: /* legacy mixer on dsp */
case SOUND_MIXER_WRITE_OGAIN: /* legacy mixer on dsp */
break;
case SNDCTL_DSP_SETPLAYVOL:
break;
case SNDCTL_DSP_READCTL:
break;
case SNDCTL_DSP_WRITECTL:
break;
case SNDCTL_DSP_COOKEDMODE:
break;
case SNDCTL_DSP_SILENCE:
rv = sndctl_dsp_silence(c);
break;
case SNDCTL_DSP_SKIP:
rv = sndctl_dsp_skip(c);
break;
case SNDCTL_DSP_HALT_INPUT:
rv = sndctl_dsp_halt_input(c);
break;
case SNDCTL_DSP_HALT_OUTPUT:
rv = sndctl_dsp_halt_output(c);
break;
break;
case SNDCTL_DSP_SETFRAGMENT:
break;
case SNDCTL_DSP_GET_RECSRC:
break;
case SNDCTL_DSP_SET_RECSRC:
break;
(oss_mixer_enuminfo *)data);
break;
case SNDCTL_DSP_GET_PLAYTGT:
break;
case SNDCTL_DSP_SET_PLAYTGT:
break;
case SNDCTL_DSP_GETRECVOL:
case SOUND_MIXER_READ_RECGAIN: /* legacy mixer on dsp */
case SOUND_MIXER_READ_RECLEV: /* legacy mixer on dsp */
case SOUND_MIXER_READ_IGAIN: /* legacy mixer on dsp */
break;
case SOUND_MIXER_WRITE_RECGAIN: /* legacy mixer on dsp */
case SOUND_MIXER_WRITE_RECLEV: /* legacy mixer on dsp */
case SOUND_MIXER_WRITE_IGAIN: /* legacy mixer on dsp */
break;
case SNDCTL_DSP_SETRECVOL:
break;
case SNDCTL_DSP_SUBDIVIDE: /* Ignored */
case SNDCTL_DSP_SETDUPLEX: /* Ignored */
case SNDCTL_DSP_LOW_WATER: /* Ignored */
case SNDCTL_DSP_PROFILE: /* Ignored */
rv = 0;
break;
case SNDCTL_DSP_POLICY:
break;
case SNDCTL_DSP_GETBLKSIZE:
break;
case SNDCTL_DSP_GETOSPACE:
break;
case SNDCTL_DSP_GETISPACE:
break;
case SNDCTL_DSP_GETODELAY:
break;
case SNDCTL_DSP_GETOPTR:
break;
case SNDCTL_DSP_GETIPTR:
break;
case SNDCTL_DSP_GETERROR:
break;
case SNDCTL_DSP_CURRENT_IPTR:
break;
case SNDCTL_DSP_CURRENT_OPTR:
break;
/*
*/
case OSS_GETVERSION:
break;
case SNDCTL_CARDINFO:
break;
case SNDCTL_ENGINEINFO:
case SNDCTL_AUDIOINFO:
case SNDCTL_AUDIOINFO_EX:
break;
case SNDCTL_SYSINFO:
break;
case SNDCTL_MIXERINFO:
break;
case SOUND_MIXER_INFO:
break;
/*
* These are mixer ioctls that are virtualized for the DSP
*/
case SOUND_MIXER_READ_RECSRC:
case SOUND_MIXER_WRITE_RECSRC:
break;
case SOUND_MIXER_READ_DEVMASK:
break;
case SOUND_MIXER_READ_RECMASK:
break;
case SOUND_MIXER_READ_CAPS:
break;
/*
* Ioctls we have chosen not to support for now. Some
* of these are of legacy interest only.
*/
case SNDCTL_SETSONG:
case SNDCTL_GETSONG:
case SNDCTL_DSP_SYNCGROUP:
case SNDCTL_DSP_SYNCSTART:
case SNDCTL_DSP_GET_CHNORDER:
case SNDCTL_DSP_SET_CHNORDER:
case SNDCTL_DSP_GETIPEAKS:
case SNDCTL_DSP_GETOPEAKS:
case SNDCTL_DSP_BIND_CHANNEL:
case SNDCTL_DSP_SETSYNCRO:
case SNDCTL_DSP_NONBLOCK:
default:
break;
}
}
if (rv == 0) {
*rvalp = 0;
}
done:
if (sz) {
}
return (rv);
}
static void
{
auclnt_pollwakeup(c, POLLOUT);
}
static void
{
}
static int
{
int rv;
if ((rv = auclnt_open(c, 0)) != 0) {
return (rv);
}
return (ENOMEM);
}
return (ENOMEM);
}
auclnt_set_private(c, sc);
/* set a couple of common fields */
return (rv);
}
static void
{
sc = auclnt_get_private(c);
auclnt_close(c);
}
static int
{
audio_dev_t *d;
d = auclnt_get_dev(c);
return (ENXIO);
}
return (EINVAL);
}
return (0);
}
static int
{
audio_dev_t *d;
int rv = 0;
int dev;
d = auclnt_get_dev(c);
return (ENXIO);
return (EINVAL);
}
return (rv);
}
static int
{
audio_dev_t *d;
int bit;
d = auclnt_get_dev(c);
return (ENXIO);
return (EINVAL);
}
bit = 0;
nxt = 0;
while (mask) {
mask >>= 1;
bit++;
}
return (0);
}
static int
{
int rv;
uint64_t v;
audio_dev_t *d;
d = auclnt_get_dev(c);
return (ENXIO);
return (EINVAL);
}
case MIXT_ENUM:
/* translate this from an enum style bit mask */
break;
case MIXT_STEREOSLIDER:
break;
case MIXT_MONOSLIDER:
break;
case MIXT_ONOFF:
/* this could be simple, or could be part of a multi */
mask = 1;
} else {
}
break;
default:
break;
}
}
return (rv);
}
static int
{
int rv;
uint64_t v;
audio_dev_t *d;
d = auclnt_get_dev(c);
return (ENXIO);
return (EINVAL);
}
case MIXT_ONOFF:
/* this could be standalone, or it could be part of a multi */
return (EINVAL);
}
mask = 1;
v |= mask;
} else {
v &= ~mask;
}
} else {
}
break;
case MIXT_ENUM:
/* translate this to an enum style bit mask */
break;
case MIXT_MONOSLIDER:
/* mask off high order bits */
break;
case MIXT_STEREOSLIDER:
/* OSS uses reverse byte ordering */
break;
default:
}
return (rv);
}
static int
{
return (0);
}
static int
int *rvalp)
{
int sz;
void *data;
int rv = 0;
return (ENOMEM);
}
} else {
sz = 0;
}
goto done;
}
}
switch (cmd) {
/*
* Mixer specific ioctls
*/
case SNDCTL_MIX_NREXT:
break;
case SNDCTL_MIX_EXTINFO:
break;
case SNDCTL_MIX_ENUMINFO:
break;
case SNDCTL_MIX_READ:
break;
case SNDCTL_MIX_WRITE:
break;
case SNDCTL_MIX_NRMIX:
break;
/*
* Legacy ioctls. These are treated as soft values only,
* and do not affect global hardware state. For use by
* legacy DSP applications.
*/
case SOUND_MIXER_READ_VOLUME:
case SOUND_MIXER_READ_PCM:
case SOUND_MIXER_READ_OGAIN:
break;
case SOUND_MIXER_WRITE_VOLUME:
case SOUND_MIXER_WRITE_PCM:
case SOUND_MIXER_WRITE_OGAIN:
break;
case SOUND_MIXER_READ_RECGAIN:
case SOUND_MIXER_READ_RECLEV:
case SOUND_MIXER_READ_IGAIN:
break;
case SOUND_MIXER_WRITE_RECLEV:
case SOUND_MIXER_WRITE_IGAIN:
break;
case SOUND_MIXER_READ_RECSRC:
case SOUND_MIXER_WRITE_RECSRC:
break;
case SOUND_MIXER_READ_DEVMASK:
break;
case SOUND_MIXER_READ_RECMASK:
break;
case SOUND_MIXER_READ_CAPS:
break;
/*
* Common ioctls shared with DSP
*/
case OSS_GETVERSION:
break;
case SNDCTL_CARDINFO:
break;
case SNDCTL_ENGINEINFO:
case SNDCTL_AUDIOINFO:
case SNDCTL_AUDIOINFO_EX:
break;
case SNDCTL_SYSINFO:
break;
case SNDCTL_MIXERINFO:
break;
case SOUND_MIXER_INFO:
break;
case SNDCTL_MIX_DESCRIPTION: /* NOT SUPPORTED: tooltip */
break;
/*
* Special implementation-private ioctls.
*/
case SNDCTL_SUN_SEND_NUMBER:
break;
/*
* Legacy ioctls we don't support.
*/
case SOUND_MIXER_READ_MONGAIN:
case SOUND_MIXER_READ_BASS:
case SOUND_MIXER_READ_TREBLE:
case SOUND_MIXER_READ_SPEAKER:
case SOUND_MIXER_READ_LINE:
case SOUND_MIXER_READ_MIC:
case SOUND_MIXER_READ_CD:
case SOUND_MIXER_READ_IMIX:
case SOUND_MIXER_READ_ALTPCM:
case SOUND_MIXER_READ_SYNTH:
case SOUND_MIXER_READ_LINE1:
case SOUND_MIXER_READ_LINE2:
case SOUND_MIXER_READ_LINE3:
case SOUND_MIXER_WRITE_BASS:
case SOUND_MIXER_WRITE_TREBLE:
case SOUND_MIXER_WRITE_LINE:
case SOUND_MIXER_WRITE_MIC:
case SOUND_MIXER_WRITE_CD:
case SOUND_MIXER_WRITE_IMIX:
case SOUND_MIXER_WRITE_ALTPCM:
case SOUND_MIXER_WRITE_SYNTH:
case SOUND_MIXER_WRITE_LINE1:
case SOUND_MIXER_WRITE_LINE2:
case SOUND_MIXER_WRITE_LINE3:
/*
* Additional ioctls we *could* support, but don't.
*/
case SNDCTL_SETSONG:
case SNDCTL_SETLABEL:
case SNDCTL_GETSONG:
case SNDCTL_GETLABEL:
case SNDCTL_MIDIINFO:
case SNDCTL_SETNAME:
default:
break;
}
}
if (rv == 0) {
*rvalp = 0;
}
done:
if (sz) {
}
return (rv);
}
static void *
{
return (odev);
}
static void
{
}
}
static void
{
}
static int
{
const char *capstr;
unsigned cap;
cap = auclnt_get_dev_capab(d);
if (cap & AUDIO_CLIENT_CAP_DUPLEX) {
capstr = "DUPLEX";
} else if ((cap & AUDIO_CLIENT_CAP_PLAY) &&
(cap & AUDIO_CLIENT_CAP_RECORD)) {
capstr = "INPUT,OUTPUT";
} else if (cap & AUDIO_CLIENT_CAP_PLAY) {
capstr = "OUTPUT";
} else if (cap & AUDIO_CLIENT_CAP_RECORD) {
capstr = "INPUT";
} else {
}
return (AUDIO_WALK_CONTINUE);
return (AUDIO_WALK_CONTINUE);
}
static int
{
unsigned cap;
void *iter;
const char *info;
cap = auclnt_get_dev_capab(d);
return (AUDIO_WALK_CONTINUE);
}
return (AUDIO_WALK_CONTINUE);
}
static int
{
/* write on sndstat is a no-op */
return (0);
}
static int
{
unsigned n;
int rv;
return (0);
}
oc = auclnt_get_private(c);
}
/*
* For simplicity's sake, we implement a non-seekable device. We could
* support seekability, but offsets would be rather meaningless between
* changes.
*/
if (rv != 0) {
n = 0;
}
if (n == 0) {
/*
* end-of-file reached... clear the sndstat buffer so that
* subsequent reads will get the latest data.
*/
}
return (rv);
}
int
{
return (auclnt_read(c, uio));
}
int
{
return (auclnt_write(c, uio));
}
int
{
}
"sound,dsp",
NULL, /* mmap */
NULL, /* drain */
};
"sound,mixer",
NULL,
NULL,
NULL, /* chpoll */
NULL, /* mmap */
NULL, /* input */
NULL, /* output */
NULL, /* drain */
NULL, /* wput */
NULL, /* wsrv */
};
/* nearly the same as ossxmix; different minor name helps devfsadm */
"sound,sndstat",
NULL, /* dev_init */
NULL, /* dev_fini */
NULL, /* chpoll */
NULL, /* mmap */
NULL, /* input */
NULL, /* output */
NULL, /* drain */
NULL, /* wput */
NULL, /* wsrv */
};
void
auimpl_oss_init(void)
{
}