88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER START
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The contents of this file are subject to the terms of the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common Development and Distribution License (the "License").
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You may not use this file except in compliance with the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the License for the specific language governing permissions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and limitations under the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER END
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic const struct {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AFMT_S24_PACKED, AUDIO_FORMAT_S24_PACKED },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* common structure shared between both mixer and dsp nodes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* sndstat */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint_t d_nalloc; /* num allocated controls */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_t **d_ctrls; /* array of control handles */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore oss_mixext *d_exts; /* array of mixer descs */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_cnt_controls(audio_ctrl_t *ctrl, void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (auclnt_control_describe(ctrl, &desc) != 0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_MULTI) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (uint64_t mask = desc.acd_maxvalue; mask; mask >>= 1) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Add one entry to the OSS user control table to internal control
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * helper table.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is used with auimpl_walk_controls. The table must be pre-
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * allocated before it is walk'd. This includes the root and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * extended control markers!
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_add_control(audio_ctrl_t *ctrl, void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Add appropriate group if not already done so.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_PLAY) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "PLAYBACK");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (desc.acd_flags & AUDIO_CTRL_FLAG_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "RECORD");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (desc.acd_flags & AUDIO_CTRL_FLAG_MONITOR) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "MONITOR");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "MISC");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_MULTI) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->extname, sizeof (ext->extname),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Next available open entry */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Record the underlying control handle */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Now setup the oss entry
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* all controls should be pollable for now */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The following flags are intended to help out applications
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * which need to figure out where to place certain controls.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * A few further words of guidance:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Apps that just want a single master volume control should
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * adjust the control(s) that are labelled with MIXF_PCMVOL if
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * present. They can fall back to adjusting all MAINVOL
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * levels instead, if no PCMVOL is present.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Controls that are one type on a certain device might be a
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * different type on another device. For example,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiopci/ak4531 can adjust input gains for individual
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * levels, but lacks a master record gain. AC'97, on the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * other hand, has individual monitor gains for inputs, but
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * only a single master recording gain.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_READABLE)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_WRITEABLE)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_CENTIBEL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_DECIBEL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_MAINVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_PCMVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_RECVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_MONVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * For now just use the same extname as the real name.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->extname, sizeof (ext->extname), name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Now we deal with various control types.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (desc.acd_flags & AUDIO_CTRL_FLAG_MULTI) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We turn AUDIO_CTRL_FLAG_MULTI into a group
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * of checkboxes, since OSS can't represent it
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NB: This is sufficient only for controls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * with a single value. It cannot express the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * richer bitmask capabilities.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * For an enumaration, we need to figure out
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * which values are present, and set the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * appropriate mask and max value.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bzero(ext->enum_present, sizeof (ext->enum_present));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Its an unknown or unsupported (for now) control, skip */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Free up an OSS user land control to internal control,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * helper table.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(odev->d_ctrls, sizeof (audio_ctrl_t *) * odev->d_nalloc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(odev->d_exts, sizeof (oss_mixext) * odev->d_nalloc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocate and fill in an OSS user land controls to internal controls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * helper table. This is done on one audio_dev device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Find out who many entries we need */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_walk_controls(d, oss_cnt_controls, &nctrl);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the device root node */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the device ext marker */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the play group */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the record group */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the monitor group */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the tone group */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nctrl++; /* Needs space for the misc group */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Allocate the OSS to boomer helper table */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore odev->d_ctrls = kmem_zalloc(sizeof (audio_ctrl_t *) * nctrl, KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore odev->d_exts = kmem_zalloc(sizeof (oss_mixext) * nctrl, KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Setup special case outputs to output OSS routes helper tables
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Root node is first, that way all others parent is this one
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ext->id, sizeof (ext->id), "DEVROOT");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Root data... nobody should be using this though.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(root_data->name, sizeof (root_data->name), "%s",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(root_data->id, sizeof (root_data->id), "%s",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Insert an extra marker -- needed to keep layout apps hapy.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This prevents some apps from assuming we are in "LEGACY" mode.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Fill in the complete table now */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_walk_controls(d, oss_add_control, odev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Update the update_counter reference counter for groups */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (nctrl = 0; nctrl < odev->d_nctrl; nctrl++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* note that OSS always uses nonblocking open() semantics */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if ((rv = auclnt_open(c, oflag | FNDELAY)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((sc = kmem_zalloc(sizeof (*sc), KM_NOSLEEP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore odev = auclnt_get_minor_data(c, AUDIO_MINOR_DSP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set a couple of common fields */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set all default parameters */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((rv = auclnt_set_format(osp, OSS_FMT)) != 0) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((rv = auclnt_set_rate(osp, OSS_RATE)) != 0) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((rv = auclnt_set_channels(osp, OSS_CHANNELS)) != 0)) {
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore /* default to 5 fragments to provide reasonable latency */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((rv = auclnt_set_format(isp, OSS_FMT)) != 0) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((rv = auclnt_set_rate(isp, OSS_RATE)) != 0) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((rv = auclnt_set_channels(isp, OSS_CHANNELS)) != 0)) {
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore /* default to 5 fragments to provide reasonable latency */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_can_receive_sig() || (ddi_get_pid() == 0)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is used to generate an array of names for an enumeration
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_set_enum(oss_mixer_enuminfo *ei, ushort_t nxt, const char *name)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Get current entry to fill in */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(&ei->strings[nxt], ((sizeof (ei->strings) - nxt) - 1),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Adjust everything for next entry */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nxt += strnlen(name, ((sizeof (ei->strings) - nxt) - 1));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The following two functions are used to count the number of devices
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * in under the boomer framework.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We actually report the highest "index", and then if an audio device
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * is not found, we report a bogus removed device for it in the actual
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ioctls. This goofiness is required to make the OSS API happy.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_speed(audio_client_t *c, int *ratep)
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_rate(auclnt_input_stream(c), rate);
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore *ratep = auclnt_get_rate(auclnt_input_stream(c));
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_rate(auclnt_output_stream(c), rate);
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore *ratep = auclnt_get_rate(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_setfmt(audio_client_t *c, int *fmtp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* convert from OSS */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; oss_formats[i].fmt != AUDIO_FORMAT_NONE; i++) {
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore /* if format not known, return */
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_format(auclnt_output_stream(c), fmt);
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_format(auclnt_input_stream(c), fmt);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fmt = auclnt_get_format(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fmt = auclnt_get_format(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* convert back to OSS */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; oss_formats[i].fmt != AUDIO_FORMAT_NONE; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getfmts(audio_client_t *c, int *fmtsp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * For now, we support all the standard ones. Later we might
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * add in conditional support for AC3.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_channels(audio_client_t *c, int *chanp)
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_channels(auclnt_output_stream(c),
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore (void) auclnt_set_channels(auclnt_input_stream(c),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nchan = auclnt_get_channels(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nchan = auclnt_get_channels(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_stereo(audio_client_t *c, int *onoff)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_output_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getcaps(audio_client_t *c, int *capsp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ncaps = auclnt_get_dev_capab(auclnt_get_dev(c));
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore osscaps |= PCM_CAP_FREERATE | PCM_CAP_MULTI;
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore /* This is the sndstat device! */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_gettrigger(audio_client_t *c, int *trigp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!auclnt_is_paused(auclnt_output_stream(c))) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!auclnt_is_paused(auclnt_input_stream(c))) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_settrigger(audio_client_t *c, int *trigp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((oflag & FWRITE) && (triggers & PCM_ENABLE_OUTPUT)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((oflag & FREAD) && (triggers & PCM_ENABLE_INPUT)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_legacy_volume_walker(audio_client_t *c, void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_set_gain(auclnt_output_stream(c), olv->ogain);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_set_gain(auclnt_input_stream(c), olv->igain);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_set_legacy_volume(audio_client_t *c, uint8_t ogain, uint8_t igain)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getplayvol(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* convert monophonic soft value to OSS stereo value */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore vol = auclnt_get_gain(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_setplayvol(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_set_gain(auclnt_output_stream(c), vol);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getrecvol(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore vol = auclnt_get_gain(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_setrecvol(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_set_gain(auclnt_input_stream(c), vol);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_write_ogain(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_write_igain(audio_client_t *c, int *volp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_readctl(audio_client_t *c, oss_digital_control *ctl)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* SPDIF: need to add support with spdif */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_writectl(audio_client_t *c, oss_digital_control *ctl)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* SPDIF: need to add support with spdif */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_cookedmode(audio_client_t *c, int *rvp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* We are *always* in cooked mode -- at least until we have AC3. */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_output_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_output_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_input_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_output_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_setfragment(audio_client_t *c, int *fragp)
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore /* use infinite setting... no change */
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore /* basically too big, so, no change */
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore * Now we have our desired buffer size, but we have to
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore * make sure we have a whole number of fragments >= 2, and
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore * less than the maximum.
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore bufsz = ((*fragp) >> 16) * (1U << (*fragp));
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore * We set the latency hints in terms of bytes, not fragments.
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore auclnt_set_latency(auclnt_output_stream(c), 0, bufsz);
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore auclnt_set_latency(auclnt_input_stream(c), 0, bufsz);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * According to the OSS API documentation, the values provided
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * are nothing more than a "hint" and not to be relied upon
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * anyway. And we aren't obligated to report the actual
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * values back!
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amoresndctl_dsp_policy(audio_client_t *c, int *policy)
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore auclnt_set_latency(auclnt_input_stream(c), hint, 0);
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore auclnt_set_latency(auclnt_output_stream(c), hint, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * A word about recsrc, and playtgt ioctls: We don't allow ordinary DSP
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * applications to change port configurations, because these could have a
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * bad effect for other applications. Instead, these settings have to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * be changed using the master mixer panel. In order to make applications
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * happy, we just present a single "default" source/target.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_get_recsrc_names(audio_client_t *c, oss_mixer_enuminfo *ei)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ei->strings, sizeof (ei->strings), "default");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_get_recsrc(audio_client_t *c, int *srcp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_set_recsrc(audio_client_t *c, int *srcp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_get_playtgt_names(audio_client_t *c, oss_mixer_enuminfo *ei)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ei->strings, sizeof (ei->strings), "default");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_get_playtgt(audio_client_t *c, int *tgtp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_set_playtgt(audio_client_t *c, int *tgtp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->product, sizeof (si->product), "SunOS Audio");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->version, sizeof (si->version), "4.0");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->license, sizeof (si->license), "CDDL");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_cardinfo(audio_client_t *c, oss_card_info *ci)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If device removed (e.g. for DR), then
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * report a bogus removed entry.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ci->shortname, sizeof (ci->shortname),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "<removed>");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ci->longname, sizeof (ci->longname),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "<removed>");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ci->shortname, sizeof (ci->shortname),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(ci->longname, sizeof (ci->longname),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore while ((info = auclnt_get_dev_hw_info(d, &iter)) != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) strlcat(ci->hw_info, info, sizeof (ci->hw_info));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) strlcat(ci->hw_info, "\n", sizeof (ci->hw_info));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We don't report interrupt counts, ack counts (which are
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * just "read" interrupts, not spurious), or any other flags.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Nothing should be using any of this data anyway ... these
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * values were intended for 4Front's debugging purposes. In
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Solaris, drivers should use interrupt kstats to report
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * interrupt related statistics.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; oss_formats[i].fmt != AUDIO_FORMAT_NONE; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore si->max_channels = max(nchan, si->max_channels);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_audioinfo(audio_client_t *c, oss_audioinfo *si)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n++; /* skip pseudo device */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if device not present, forge a false entry */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->name, sizeof (si->name), "<removed>");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->name, sizeof (si->name), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore si->legacy_device = auclnt_get_dev_number(d);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_dev_walk_engines(d, audioinfo_walker, si);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* MMAP: we add PCM_CAP_MMAP when we we support it */
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore si->caps |= PCM_CAP_TRIGGER | PCM_CAP_BATCH;
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore /* we can convert and mix PCM formats */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore si->min_channels = min(2, si->max_channels);
260256302ac564fcfed9ebfa5a6c98a2e6ef3808Garrett D'Amore si->caps |= PCM_CAP_FREERATE | PCM_CAP_MULTI;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->devnode, sizeof (si->devnode),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_driver(d), auclnt_get_dev_instance(d));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore si->enabled = 0; /* stops apps from using us directly */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->devnode, sizeof (si->devnode),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->handle, sizeof (si->handle), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(si->label, sizeof (si->label), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_info(audio_client_t *c, mixer_info *mi)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->id, sizeof (mi->id), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->name, sizeof (mi->name), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->handle, sizeof (mi->handle), "%s", name);
682cb1044237d21ad6810702564bec833b8c410cGarrett D'Amore mi->modify_counter = (int)auclnt_dev_get_serial(d);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_read_devmask(audio_client_t *c, int *devmask)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *devmask = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_IGAIN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_read_recmask(audio_client_t *c, int *recmask)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_read_recsrc(audio_client_t *c, int *recsrc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresound_mixer_read_caps(audio_client_t *c, int *caps)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* single recording source... sort of */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mixerinfo(audio_client_t *c, oss_mixerinfo *mi)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->name, sizeof (mi->name), "<removed>");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->id, sizeof (mi->id), "<removed>");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->name, sizeof (mi->name), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->id, sizeof (mi->id), "%s", name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->handle, sizeof (mi->handle), "%s", name);
682cb1044237d21ad6810702564bec833b8c410cGarrett D'Amore mi->modify_counter = (int)auclnt_dev_get_serial(d);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mi->legacy_device = auclnt_get_dev_number(d);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->devnode, sizeof (mi->devnode),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "/dev/sound/%s:%dmixer",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_driver(d), auclnt_get_dev_instance(d));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* special nodes use generic sndstat node */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) snprintf(mi->devnode, sizeof (mi->devnode),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getblksize(audio_client_t *c, int *fragsz)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *fragsz = auclnt_get_fragsz(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *fragsz = auclnt_get_fragsz(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getospace(audio_client_t *c, audio_buf_info *bi)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n = auclnt_get_nframes(sp) - auclnt_get_count(sp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getispace(audio_client_t *c, audio_buf_info *bi)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getodelay(audio_client_t *c, int *bytes)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_stream_t *sp = auclnt_output_stream(c);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_current_iptr(audio_client_t *c, oss_count_t *count)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore count->samples = auclnt_get_samples(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore count->fifo_samples = 0; /* not quite accurate */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_current_optr(audio_client_t *c, oss_count_t *count)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getoptr(audio_client_t *c, count_info *ci)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ci->blocks = auclnt_get_samples(sp) * framesz / fragsz;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_getiptr(audio_client_t *c, count_info *ci)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ci->blocks = auclnt_get_samples(sp) * framesz / fragsz;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_dsp_geterror(audio_client_t *c, audio_errinfo *bi)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note: The use of this structure is unsafe... different
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * meanings for error codes are used by different implementations,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * according to the spec. (Even different versions of the same
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * implementation could have different values.)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Rather than try to come up with a reliable solution here, we
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * don't use it. If you want to report errors, or see the result
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * of errors, use syslog.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bi->play_underruns = (int)((auclnt_get_errors(sp) + (fragsz - 1)) /
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bi->rec_overruns = (int)((auclnt_get_errors(sp) + (fragsz - 1)) /
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_sun_send_number(audio_client_t *c, int *num, cred_t *cr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_ioctl(audio_client_t *c, int cmd, intptr_t arg, int mode, cred_t *credp,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((cmd & (OSSIOC_IN | OSSIOC_OUT)) && sz) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((data = kmem_zalloc(sz, KM_NOSLEEP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = ddi_copyin((void *)arg, data, sz, mode)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DSP specific ioctls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_VOLUME: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_PCM: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_OGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_VOLUME: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_PCM: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_OGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_write_ogain(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_readctl(c, (oss_digital_control *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_writectl(c, (oss_digital_control *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_get_recsrc_names(c, (oss_mixer_enuminfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_setfragment(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_get_playtgt(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_set_playtgt(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_RECGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_RECLEV: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_READ_IGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_RECGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_RECLEV: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SOUND_MIXER_WRITE_IGAIN: /* legacy mixer on dsp */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_write_igain(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_getospace(c, (audio_buf_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_getispace(c, (audio_buf_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_getoptr(c, (count_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_getiptr(c, (count_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_geterror(c, (audio_errinfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_current_iptr(c, (oss_count_t *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_dsp_current_optr(c, (oss_count_t *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Shared ioctls with /dev/mixer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_cardinfo(c, (oss_card_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_audioinfo(c, (oss_audioinfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mixerinfo(c, (oss_mixerinfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_info(c, (mixer_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * These are mixer ioctls that are virtualized for the DSP
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * device. They are accessible via either /dev/mixer or
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_recsrc(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_devmask(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_recmask(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Ioctls we have chosen not to support for now. Some
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * of these are of legacy interest only.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = ddi_copyout(data, (void *)arg, sz, mode);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((sc = kmem_zalloc(sizeof (*sc), KM_NOSLEEP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((sc->o_ss_buf = kmem_zalloc(sc->o_ss_sz, KM_NOSLEEP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore odev = auclnt_get_minor_data(c, AUDIO_MINOR_DSP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set a couple of common fields */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_nrext(audio_client_t *c, int *ncp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((*ncp != -1) && (*ncp != (auclnt_get_dev_index(d) - 1))) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_extinfo(audio_client_t *c, oss_mixext *pext)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((dev = pext->dev) != -1) && (dev != (auclnt_get_dev_index(d) - 1)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bcopy(&odev->d_exts[pext->ctrl], pext, sizeof (*pext));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_enuminfo(audio_client_t *c, oss_mixer_enuminfo *ei)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((ei->dev != -1) && (ei->dev != (auclnt_get_dev_index(d) - 1)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (odev->d_exts[ei->ctrl].type != MIXT_ENUM) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((ctrl = odev->d_ctrls[ei->ctrl]) == NULL) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (auclnt_control_describe(ctrl, &desc) != 0)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nxt = oss_set_enum(ei, nxt, name ? name : "");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_read(audio_client_t *c, oss_mixer_value *vr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((vr->dev != -1) && (vr->dev != (auclnt_get_dev_index(d) - 1)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((ctrl = odev->d_ctrls[vr->ctrl]) == NULL)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = auclnt_control_read(ctrl, &v)) == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* translate this from an enum style bit mask */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* this could be simple, or could be part of a multi */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_write(audio_client_t *c, oss_mixer_value *vr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((vr->dev != -1) && (vr->dev != (auclnt_get_dev_index(d) - 1)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((odev = auclnt_get_dev_minor_data(d, AUDIO_MINOR_DSP)) == NULL) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((ctrl = odev->d_ctrls[vr->ctrl]) == NULL)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* this could be standalone, or it could be part of a multi */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = auclnt_control_read(ctrl, &v)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* translate this to an enum style bit mask */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* mask off high order bits */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* OSS uses reverse byte ordering */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndctl_mix_nrmix(audio_client_t *c, int *nmixp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreossmix_ioctl(audio_client_t *c, int cmd, intptr_t arg, int mode, cred_t *credp,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((cmd & (OSSIOC_IN | OSSIOC_OUT)) && sz) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((data = kmem_zalloc(sz, KM_NOSLEEP)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = ddi_copyin((void *)arg, data, sz, mode)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Mixer specific ioctls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mix_extinfo(c, (oss_mixext *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mix_enuminfo(c, (oss_mixer_enuminfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mix_read(c, (oss_mixer_value *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mix_write(c, (oss_mixer_value *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Legacy ioctls. These are treated as soft values only,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and do not affect global hardware state. For use by
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * legacy DSP applications.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_write_ogain(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_write_igain(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_recsrc(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_devmask(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_read_recmask(c, (int *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common ioctls shared with DSP
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_cardinfo(c, (oss_card_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_audioinfo(c, (oss_audioinfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_mixerinfo(c, (oss_mixerinfo *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sound_mixer_info(c, (mixer_info *)data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case SNDCTL_MIX_DESCRIPTION: /* NOT SUPPORTED: tooltip */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = EIO; /* OSS returns EIO for this one */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Special implementation-private ioctls.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = sndctl_sun_send_number(c, (int *)data, credp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Legacy ioctls we don't support.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Additional ioctls we *could* support, but don't.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = ddi_copyout(data, (void *)arg, sz, mode);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore odev = kmem_zalloc(sizeof (*odev), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_init(&odev->d_mx, NULL, MUTEX_DRIVER, NULL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cv_init(&odev->d_cv, NULL, CV_DRIVER, NULL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndstat_printf(ossclient_t *oc, const char *fmt, ...)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) vsnprintf(oc->o_ss_buf + oc->o_ss_len,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndstat_dev_walker(audio_dev_t *d, void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_number(d), auclnt_get_dev_name(d),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_description(d), auclnt_get_dev_version(d), capstr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresndstat_mixer_walker(audio_dev_t *d, void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((cap & (AUDIO_CLIENT_CAP_PLAY|AUDIO_CLIENT_CAP_RECORD)) == 0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_number(d), auclnt_get_dev_name(d),
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_get_dev_description(d), auclnt_get_dev_version(d));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore while ((info = auclnt_get_dev_hw_info(d, &iter)) != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreossmix_write(audio_client_t *c, struct uio *uio, cred_t *cr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* write on sndstat is a no-op */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreossmix_read(audio_client_t *c, struct uio *uio, cred_t *cr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sndstat_printf(oc, "SunOS Audio Framework\n");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_walk_devs_by_number(sndstat_dev_walker, oc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_walk_devs_by_number(sndstat_mixer_walker, oc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * For simplicity's sake, we implement a non-seekable device. We could
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * support seekability, but offsets would be rather meaningless between
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n = min(uio->uio_resid, (oc->o_ss_len - oc->o_ss_off));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = uiomove(oc->o_ss_buf + oc->o_ss_off, n, UIO_READ, uio);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (n == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * end-of-file reached... clear the sndstat buffer so that
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * subsequent reads will get the latest data.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_read(audio_client_t *c, struct uio *uio, cred_t *cr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_clear_paused(auclnt_input_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_write(audio_client_t *c, struct uio *uio, cred_t *cr)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_clear_paused(auclnt_output_stream(c));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreoss_chpoll(audio_client_t *c, short events, int anyyet, short *reventsp,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (auclnt_chpoll(c, events, anyyet, reventsp, phpp));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct audio_client_ops ossmix_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "sound,mixer",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* nearly the same as ossxmix; different minor name helps devfsadm */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct audio_client_ops sndstat_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "sound,sndstat",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_register_ops(AUDIO_MINOR_DSP, &oss_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auclnt_register_ops(AUDIO_MINOR_MIXER, &ossmix_ops);