xref: /freebsd/sys/dev/sound/pcm/mixer.c (revision 29ff7b08be363f0d4345794bb951d5c0c8406a0a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
5  * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
6  * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifdef HAVE_KERNEL_OPTION_HEADERS
32 #include "opt_snd.h"
33 #endif
34 
35 #include <dev/sound/pcm/sound.h>
36 
37 #include "feeder_if.h"
38 #include "mixer_if.h"
39 
40 static MALLOC_DEFINE(M_MIXER, "mixer", "mixer");
41 
42 static int mixer_bypass = 1;
43 SYSCTL_INT(_hw_snd, OID_AUTO, vpc_mixer_bypass, CTLFLAG_RWTUN,
44     &mixer_bypass, 0,
45     "control channel pcm/rec volume, bypassing real mixer device");
46 
47 #define MIXER_NAMELEN	16
48 struct snd_mixer {
49 	KOBJ_FIELDS;
50 	void *devinfo;
51 	int busy;
52 	int hwvol_mixer;
53 	int hwvol_step;
54 	int type;
55 	device_t dev;
56 	u_int32_t devs;
57 	u_int32_t mutedevs;
58 	u_int32_t recdevs;
59 	u_int32_t recsrc;
60 	u_int16_t level[32];
61 	u_int16_t level_muted[32];
62 	u_int8_t parent[32];
63 	u_int32_t child[32];
64 	u_int8_t realdev[32];
65 	char name[MIXER_NAMELEN];
66 	struct mtx *lock;
67 	oss_mixer_enuminfo enuminfo;
68 	/**
69 	 * Counter is incremented when applications change any of this
70 	 * mixer's controls.  A change in value indicates that persistent
71 	 * mixer applications should update their displays.
72 	 */
73 	int modify_counter;
74 };
75 
76 static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
77 	[SOUND_MIXER_VOLUME]	= 75,
78 	[SOUND_MIXER_BASS]	= 50,
79 	[SOUND_MIXER_TREBLE]	= 50,
80 	[SOUND_MIXER_SYNTH]	= 75,
81 	[SOUND_MIXER_PCM]	= 75,
82 	[SOUND_MIXER_SPEAKER]	= 75,
83 	[SOUND_MIXER_LINE]	= 75,
84 	[SOUND_MIXER_MIC] 	= 25,
85 	[SOUND_MIXER_CD]	= 75,
86 	[SOUND_MIXER_IGAIN]	= 0,
87 	[SOUND_MIXER_LINE1]	= 75,
88 	[SOUND_MIXER_VIDEO]	= 75,
89 	[SOUND_MIXER_RECLEV]	= 75,
90 	[SOUND_MIXER_OGAIN]	= 50,
91 	[SOUND_MIXER_MONITOR]	= 75,
92 };
93 
94 static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
95 
96 static d_open_t mixer_open;
97 static d_close_t mixer_close;
98 static d_ioctl_t mixer_ioctl;
99 
100 static struct cdevsw mixer_cdevsw = {
101 	.d_version =	D_VERSION,
102 	.d_open =	mixer_open,
103 	.d_close =	mixer_close,
104 	.d_ioctl =	mixer_ioctl,
105 	.d_name =	"mixer",
106 };
107 
108 static eventhandler_tag mixer_ehtag = NULL;
109 
110 static struct cdev *
111 mixer_get_devt(device_t dev)
112 {
113 	struct snddev_info *snddev;
114 
115 	snddev = device_get_softc(dev);
116 
117 	return snddev->mixer_dev;
118 }
119 
120 static int
121 mixer_lookup(char *devname)
122 {
123 	int i;
124 
125 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
126 		if (strncmp(devname, snd_mixernames[i],
127 		    strlen(snd_mixernames[i])) == 0)
128 			return i;
129 	return -1;
130 }
131 
132 #define MIXER_SET_UNLOCK(x, y)		do {				\
133 	if ((y) != 0)							\
134 		snd_mtxunlock((x)->lock);				\
135 } while (0)
136 
137 #define MIXER_SET_LOCK(x, y)		do {				\
138 	if ((y) != 0)							\
139 		snd_mtxlock((x)->lock);					\
140 } while (0)
141 
142 static int
143 mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
144     u_int left, u_int right)
145 {
146 	struct pcm_channel *c;
147 	int dropmtx, acquiremtx;
148 
149 	if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
150 		return (EINVAL);
151 
152 	if (mtx_owned(m->lock))
153 		dropmtx = 1;
154 	else
155 		dropmtx = 0;
156 
157 	if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
158 		acquiremtx = 0;
159 	else
160 		acquiremtx = 1;
161 
162 	/*
163 	 * Be careful here. If we're coming from cdev ioctl, it is OK to
164 	 * not doing locking AT ALL (except on individual channel) since
165 	 * we've been heavily guarded by pcm cv, or if we're still
166 	 * under Giant influence. Since we also have mix_* calls, we cannot
167 	 * assume such protection and just do the lock as usuall.
168 	 */
169 	MIXER_SET_UNLOCK(m, dropmtx);
170 	MIXER_SET_LOCK(d, acquiremtx);
171 
172 	CHN_FOREACH(c, d, channels.pcm.busy) {
173 		CHN_LOCK(c);
174 		if (c->direction == PCMDIR_PLAY &&
175 		    (c->feederflags & (1 << FEEDER_VOLUME)))
176 			chn_setvolume_multi(c, SND_VOL_C_MASTER, left, right,
177 			    (left + right) >> 1);
178 		CHN_UNLOCK(c);
179 	}
180 
181 	MIXER_SET_UNLOCK(d, acquiremtx);
182 	MIXER_SET_LOCK(m, dropmtx);
183 
184 	return (0);
185 }
186 
187 static int
188 mixer_set_eq(struct snd_mixer *m, struct snddev_info *d,
189     u_int dev, u_int level)
190 {
191 	struct pcm_channel *c;
192 	struct pcm_feeder *f;
193 	int tone, dropmtx, acquiremtx;
194 
195 	if (dev == SOUND_MIXER_TREBLE)
196 		tone = FEEDEQ_TREBLE;
197 	else if (dev == SOUND_MIXER_BASS)
198 		tone = FEEDEQ_BASS;
199 	else
200 		return (EINVAL);
201 
202 	if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
203 		return (EINVAL);
204 
205 	if (mtx_owned(m->lock))
206 		dropmtx = 1;
207 	else
208 		dropmtx = 0;
209 
210 	if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
211 		acquiremtx = 0;
212 	else
213 		acquiremtx = 1;
214 
215 	/*
216 	 * Be careful here. If we're coming from cdev ioctl, it is OK to
217 	 * not doing locking AT ALL (except on individual channel) since
218 	 * we've been heavily guarded by pcm cv, or if we're still
219 	 * under Giant influence. Since we also have mix_* calls, we cannot
220 	 * assume such protection and just do the lock as usuall.
221 	 */
222 	MIXER_SET_UNLOCK(m, dropmtx);
223 	MIXER_SET_LOCK(d, acquiremtx);
224 
225 	CHN_FOREACH(c, d, channels.pcm.busy) {
226 		CHN_LOCK(c);
227 		f = feeder_find(c, FEEDER_EQ);
228 		if (f != NULL)
229 			(void)FEEDER_SET(f, tone, level);
230 		CHN_UNLOCK(c);
231 	}
232 
233 	MIXER_SET_UNLOCK(d, acquiremtx);
234 	MIXER_SET_LOCK(m, dropmtx);
235 
236 	return (0);
237 }
238 
239 static int
240 mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
241 {
242 	struct snddev_info *d;
243 	u_int l, r, tl, tr;
244 	u_int32_t parent = SOUND_MIXER_NONE, child = 0;
245 	u_int32_t realdev;
246 	int i, dropmtx;
247 
248 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
249 	    (0 == (m->devs & (1 << dev))))
250 		return (-1);
251 
252 	l = min((lev & 0x00ff), 100);
253 	r = min(((lev & 0xff00) >> 8), 100);
254 	realdev = m->realdev[dev];
255 
256 	d = device_get_softc(m->dev);
257 	if (d == NULL)
258 		return (-1);
259 
260 	/* It is safe to drop this mutex due to Giant. */
261 	if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
262 		dropmtx = 1;
263 	else
264 		dropmtx = 0;
265 
266 	/* Allow the volume to be "changed" while muted. */
267 	if (muted & (1 << dev)) {
268 		m->level_muted[dev] = l | (r << 8);
269 		return (0);
270 	}
271 	MIXER_SET_UNLOCK(m, dropmtx);
272 
273 	/* TODO: recursive handling */
274 	parent = m->parent[dev];
275 	if (parent >= SOUND_MIXER_NRDEVICES)
276 		parent = SOUND_MIXER_NONE;
277 	if (parent == SOUND_MIXER_NONE)
278 		child = m->child[dev];
279 
280 	if (parent != SOUND_MIXER_NONE) {
281 		tl = (l * (m->level[parent] & 0x00ff)) / 100;
282 		tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100;
283 		if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
284 			(void)mixer_set_softpcmvol(m, d, tl, tr);
285 		else if (realdev != SOUND_MIXER_NONE &&
286 		    MIXER_SET(m, realdev, tl, tr) < 0) {
287 			MIXER_SET_LOCK(m, dropmtx);
288 			return (-1);
289 		}
290 	} else if (child != 0) {
291 		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
292 			if (!(child & (1 << i)) || m->parent[i] != dev)
293 				continue;
294 			realdev = m->realdev[i];
295 			tl = (l * (m->level[i] & 0x00ff)) / 100;
296 			tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100;
297 			if (i == SOUND_MIXER_PCM &&
298 			    (d->flags & SD_F_SOFTPCMVOL))
299 				(void)mixer_set_softpcmvol(m, d, tl, tr);
300 			else if (realdev != SOUND_MIXER_NONE)
301 				MIXER_SET(m, realdev, tl, tr);
302 		}
303 		realdev = m->realdev[dev];
304 		if (realdev != SOUND_MIXER_NONE &&
305 		    MIXER_SET(m, realdev, l, r) < 0) {
306 			MIXER_SET_LOCK(m, dropmtx);
307 			return (-1);
308 		}
309 	} else {
310 		if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
311 			(void)mixer_set_softpcmvol(m, d, l, r);
312 		else if ((dev == SOUND_MIXER_TREBLE ||
313 		    dev == SOUND_MIXER_BASS) && (d->flags & SD_F_EQ))
314 			(void)mixer_set_eq(m, d, dev, (l + r) >> 1);
315 		else if (realdev != SOUND_MIXER_NONE &&
316 		    MIXER_SET(m, realdev, l, r) < 0) {
317 			MIXER_SET_LOCK(m, dropmtx);
318 			return (-1);
319 		}
320 	}
321 
322 	MIXER_SET_LOCK(m, dropmtx);
323 
324 	m->level[dev] = l | (r << 8);
325 	m->modify_counter++;
326 
327 	return (0);
328 }
329 
330 static int
331 mixer_get(struct snd_mixer *mixer, int dev)
332 {
333 	if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) {
334 		if (mixer->mutedevs & (1 << dev))
335 			return (mixer->level_muted[dev]);
336 		else
337 			return (mixer->level[dev]);
338 	} else {
339 		return (-1);
340 	}
341 }
342 
343 void
344 mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs)
345 {
346 	u_int32_t delta;
347 
348 	/* Filter out invalid values. */
349 	mutedevs &= mixer->devs;
350 	delta = (mixer->mutedevs ^ mutedevs) & mixer->devs;
351 	mixer->mutedevs = mutedevs;
352 
353 	for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
354 		if (!(delta & (1 << i)))
355 			continue;
356 		if (mutedevs & (1 << i)) {
357 			mixer->level_muted[i] = mixer->level[i];
358 			mixer_set(mixer, i, 0, 0);
359 		} else {
360 			mixer_set(mixer, i, 0, mixer->level_muted[i]);
361 		}
362 	}
363 }
364 
365 static int
366 mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
367 {
368 	struct snddev_info *d;
369 	u_int32_t recsrc;
370 	int dropmtx;
371 
372 	d = device_get_softc(mixer->dev);
373 	if (d == NULL)
374 		return -1;
375 	if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
376 		dropmtx = 1;
377 	else
378 		dropmtx = 0;
379 	src &= mixer->recdevs;
380 	if (src == 0)
381 		src = mixer->recdevs & SOUND_MASK_MIC;
382 	if (src == 0)
383 		src = mixer->recdevs & SOUND_MASK_MONITOR;
384 	if (src == 0)
385 		src = mixer->recdevs & SOUND_MASK_LINE;
386 	if (src == 0 && mixer->recdevs != 0)
387 		src = (1 << (ffs(mixer->recdevs) - 1));
388 	/* It is safe to drop this mutex due to Giant. */
389 	MIXER_SET_UNLOCK(mixer, dropmtx);
390 	recsrc = MIXER_SETRECSRC(mixer, src);
391 	MIXER_SET_LOCK(mixer, dropmtx);
392 
393 	mixer->recsrc = recsrc;
394 
395 	return 0;
396 }
397 
398 static int
399 mixer_getrecsrc(struct snd_mixer *mixer)
400 {
401 	return mixer->recsrc;
402 }
403 
404 /**
405  * @brief Retrieve the route number of the current recording device
406  *
407  * OSSv4 assigns routing numbers to recording devices, unlike the previous
408  * API which relied on a fixed table of device numbers and names.  This
409  * function returns the routing number of the device currently selected
410  * for recording.
411  *
412  * For now, this function is kind of a goofy compatibility stub atop the
413  * existing sound system.  (For example, in theory, the old sound system
414  * allows multiple recording devices to be specified via a bitmask.)
415  *
416  * @param m	mixer context container thing
417  *
418  * @retval 0		success
419  * @retval EIDRM	no recording device found (generally not possible)
420  * @todo Ask about error code
421  */
422 static int
423 mixer_get_recroute(struct snd_mixer *m, int *route)
424 {
425 	int i, cnt;
426 
427 	cnt = 0;
428 
429 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
430 		/** @todo can user set a multi-device mask? (== or &?) */
431 		if ((1 << i) == m->recsrc)
432 			break;
433 		if ((1 << i) & m->recdevs)
434 			++cnt;
435 	}
436 
437 	if (i == SOUND_MIXER_NRDEVICES)
438 		return EIDRM;
439 
440 	*route = cnt;
441 	return 0;
442 }
443 
444 /**
445  * @brief Select a device for recording
446  *
447  * This function sets a recording source based on a recording device's
448  * routing number.  Said number is translated to an old school recdev
449  * mask and passed over mixer_setrecsrc.
450  *
451  * @param m	mixer context container thing
452  *
453  * @retval 0		success(?)
454  * @retval EINVAL	User specified an invalid device number
455  * @retval otherwise	error from mixer_setrecsrc
456  */
457 static int
458 mixer_set_recroute(struct snd_mixer *m, int route)
459 {
460 	int i, cnt, ret;
461 
462 	ret = 0;
463 	cnt = 0;
464 
465 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
466 		if ((1 << i) & m->recdevs) {
467 			if (route == cnt)
468 				break;
469 			++cnt;
470 		}
471 	}
472 
473 	if (i == SOUND_MIXER_NRDEVICES)
474 		ret = EINVAL;
475 	else
476 		ret = mixer_setrecsrc(m, (1 << i));
477 
478 	return ret;
479 }
480 
481 void
482 mix_setdevs(struct snd_mixer *m, u_int32_t v)
483 {
484 	struct snddev_info *d;
485 	int i;
486 
487 	if (m == NULL)
488 		return;
489 
490 	d = device_get_softc(m->dev);
491 	if (d != NULL && (d->flags & SD_F_SOFTPCMVOL))
492 		v |= SOUND_MASK_PCM;
493 	if (d != NULL && (d->flags & SD_F_EQ))
494 		v |= SOUND_MASK_TREBLE | SOUND_MASK_BASS;
495 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
496 		if (m->parent[i] < SOUND_MIXER_NRDEVICES)
497 			v |= 1 << m->parent[i];
498 		v |= m->child[i];
499 	}
500 	m->devs = v;
501 }
502 
503 /**
504  * @brief Record mask of available recording devices
505  *
506  * Calling functions are responsible for defining the mask of available
507  * recording devices.  This function records that value in a structure
508  * used by the rest of the mixer code.
509  *
510  * This function also populates a structure used by the SNDCTL_DSP_*RECSRC*
511  * family of ioctls that are part of OSSV4.  All recording device labels
512  * are concatenated in ascending order corresponding to their routing
513  * numbers.  (Ex:  a system might have 0 => 'vol', 1 => 'cd', 2 => 'line',
514  * etc.)  For now, these labels are just the standard recording device
515  * names (cd, line1, etc.), but will eventually be fully dynamic and user
516  * controlled.
517  *
518  * @param m	mixer device context container thing
519  * @param v	mask of recording devices
520  */
521 void
522 mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
523 {
524 	oss_mixer_enuminfo *ei;
525 	char *loc;
526 	int i, nvalues, nwrote, nleft, ncopied;
527 
528 	ei = &m->enuminfo;
529 
530 	nvalues = 0;
531 	nwrote = 0;
532 	nleft = sizeof(ei->strings);
533 	loc = ei->strings;
534 
535 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
536 		if ((1 << i) & v) {
537 			ei->strindex[nvalues] = nwrote;
538 			ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1;
539 			    /* strlcpy retval doesn't include terminator */
540 
541 			nwrote += ncopied;
542 			nleft -= ncopied;
543 			nvalues++;
544 
545 			/*
546 			 * XXX I don't think this should ever be possible.
547 			 * Even with a move to dynamic device/channel names,
548 			 * each label is limited to ~16 characters, so that'd
549 			 * take a LOT to fill this buffer.
550 			 */
551 			if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
552 				device_printf(m->dev,
553 				    "mix_setrecdevs:  Not enough room to store device names--please file a bug report.\n");
554 				device_printf(m->dev,
555 				    "mix_setrecdevs:  Please include details about your sound hardware, OS version, etc.\n");
556 				break;
557 			}
558 
559 			loc = &ei->strings[nwrote];
560 		}
561 	}
562 
563 	/*
564 	 * NB:	The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev
565 	 * 	and ctrl fields.
566 	 */
567 	ei->nvalues = nvalues;
568 	m->recdevs = v;
569 }
570 
571 void
572 mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
573 {
574 	u_int32_t mask = 0;
575 	int i;
576 
577 	if (m == NULL || parent >= SOUND_MIXER_NRDEVICES)
578 		return;
579 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
580 		if (i == parent)
581 			continue;
582 		if (childs & (1 << i)) {
583 			mask |= 1 << i;
584 			if (m->parent[i] < SOUND_MIXER_NRDEVICES)
585 				m->child[m->parent[i]] &= ~(1 << i);
586 			m->parent[i] = parent;
587 			m->child[i] = 0;
588 		}
589 	}
590 	mask &= ~(1 << parent);
591 	m->child[parent] = mask;
592 }
593 
594 void
595 mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
596 {
597 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
598 	    !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
599 		return;
600 	m->realdev[dev] = realdev;
601 }
602 
603 u_int32_t
604 mix_getparent(struct snd_mixer *m, u_int32_t dev)
605 {
606 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
607 		return SOUND_MIXER_NONE;
608 	return m->parent[dev];
609 }
610 
611 u_int32_t
612 mix_getchild(struct snd_mixer *m, u_int32_t dev)
613 {
614 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
615 		return 0;
616 	return m->child[dev];
617 }
618 
619 u_int32_t
620 mix_getdevs(struct snd_mixer *m)
621 {
622 	return m->devs;
623 }
624 
625 u_int32_t
626 mix_getmutedevs(struct snd_mixer *m)
627 {
628 	return m->mutedevs;
629 }
630 
631 u_int32_t
632 mix_getrecdevs(struct snd_mixer *m)
633 {
634 	return m->recdevs;
635 }
636 
637 void *
638 mix_getdevinfo(struct snd_mixer *m)
639 {
640 	return m->devinfo;
641 }
642 
643 static struct snd_mixer *
644 mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo,
645     int type, const char *desc)
646 {
647 	struct snd_mixer *m;
648 	size_t i;
649 
650 	KASSERT(dev != NULL && cls != NULL && devinfo != NULL,
651 	    ("%s(): NULL data dev=%p cls=%p devinfo=%p",
652 	    __func__, dev, cls, devinfo));
653 	KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY,
654 	    ("invalid mixer type=%d", type));
655 
656 	m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
657 	snprintf(m->name, sizeof(m->name), "%s:mixer",
658 	    device_get_nameunit(dev));
659 	if (desc != NULL) {
660 		strlcat(m->name, ":", sizeof(m->name));
661 		strlcat(m->name, desc, sizeof(m->name));
662 	}
663 	m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ?
664 	    "primary pcm mixer" : "secondary pcm mixer");
665 	m->type = type;
666 	m->devinfo = devinfo;
667 	m->busy = 0;
668 	m->dev = dev;
669 	for (i = 0; i < nitems(m->parent); i++) {
670 		m->parent[i] = SOUND_MIXER_NONE;
671 		m->child[i] = 0;
672 		m->realdev[i] = i;
673 	}
674 
675 	if (MIXER_INIT(m)) {
676 		snd_mtxlock(m->lock);
677 		snd_mtxfree(m->lock);
678 		kobj_delete((kobj_t)m, M_MIXER);
679 		return (NULL);
680 	}
681 
682 	return (m);
683 }
684 
685 int
686 mixer_delete(struct snd_mixer *m)
687 {
688 	KASSERT(m != NULL, ("NULL snd_mixer"));
689 	KASSERT(m->type == MIXER_TYPE_SECONDARY,
690 	    ("%s(): illegal mixer type=%d", __func__, m->type));
691 
692 	/* mixer uninit can sleep --hps */
693 
694 	MIXER_UNINIT(m);
695 
696 	snd_mtxfree(m->lock);
697 	kobj_delete((kobj_t)m, M_MIXER);
698 
699 	return (0);
700 }
701 
702 struct snd_mixer *
703 mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
704 {
705 	return (mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc));
706 }
707 
708 int
709 mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
710 {
711 	struct snddev_info *snddev;
712 	struct snd_mixer *m;
713 	u_int16_t v;
714 	struct cdev *pdev;
715 	const char *name;
716 	int i, unit, val;
717 
718 	snddev = device_get_softc(dev);
719 	if (snddev == NULL)
720 		return (-1);
721 
722 	name = device_get_name(dev);
723 	unit = device_get_unit(dev);
724 	if (resource_int_value(name, unit, "eq", &val) == 0 &&
725 	    val != 0) {
726 		snddev->flags |= SD_F_EQ;
727 		if ((val & SD_F_EQ_MASK) == val)
728 			snddev->flags |= val;
729 		else
730 			snddev->flags |= SD_F_EQ_DEFAULT;
731 		snddev->eqpreamp = 0;
732 	}
733 
734 	m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL);
735 	if (m == NULL)
736 		return (-1);
737 
738 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
739 		v = snd_mixerdefaults[i];
740 
741 		if (resource_int_value(name, unit, snd_mixernames[i],
742 		    &val) == 0) {
743 			if (val >= 0 && val <= 100) {
744 				v = (u_int16_t) val;
745 			}
746 		}
747 
748 		mixer_set(m, i, 0, v | (v << 8));
749 	}
750 
751 	mixer_setrecsrc(m, 0); /* Set default input. */
752 
753 	pdev = make_dev(&mixer_cdevsw, SND_DEV_CTL, UID_ROOT, GID_WHEEL, 0666,
754 	    "mixer%d", unit);
755 	pdev->si_drv1 = m;
756 	snddev->mixer_dev = pdev;
757 
758 	if (bootverbose) {
759 		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
760 			if (!(m->devs & (1 << i)))
761 				continue;
762 			if (m->realdev[i] != i) {
763 				device_printf(dev, "Mixer \"%s\" -> \"%s\":",
764 				    snd_mixernames[i],
765 				    (m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
766 				    snd_mixernames[m->realdev[i]] : "none");
767 			} else {
768 				device_printf(dev, "Mixer \"%s\":",
769 				    snd_mixernames[i]);
770 			}
771 			if (m->parent[i] < SOUND_MIXER_NRDEVICES)
772 				printf(" parent=\"%s\"",
773 				    snd_mixernames[m->parent[i]]);
774 			if (m->child[i] != 0)
775 				printf(" child=0x%08x", m->child[i]);
776 			printf("\n");
777 		}
778 		if (snddev->flags & SD_F_SOFTPCMVOL)
779 			device_printf(dev, "Soft PCM mixer ENABLED\n");
780 		if (snddev->flags & SD_F_EQ)
781 			device_printf(dev, "EQ Treble/Bass ENABLED\n");
782 	}
783 
784 	return (0);
785 }
786 
787 int
788 mixer_uninit(device_t dev)
789 {
790 	int i;
791 	struct snddev_info *d;
792 	struct snd_mixer *m;
793 	struct cdev *pdev;
794 
795 	d = device_get_softc(dev);
796 	pdev = mixer_get_devt(dev);
797 	if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
798 		return EBADF;
799 
800 	m = pdev->si_drv1;
801 	KASSERT(m != NULL, ("NULL snd_mixer"));
802 	KASSERT(m->type == MIXER_TYPE_PRIMARY,
803 	    ("%s(): illegal mixer type=%d", __func__, m->type));
804 
805 	pdev->si_drv1 = NULL;
806 	destroy_dev(pdev);
807 
808 	snd_mtxlock(m->lock);
809 
810 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
811 		mixer_set(m, i, 0, 0);
812 
813 	mixer_setrecsrc(m, SOUND_MASK_MIC);
814 
815 	snd_mtxunlock(m->lock);
816 
817 	/* mixer uninit can sleep --hps */
818 
819 	MIXER_UNINIT(m);
820 
821 	snd_mtxfree(m->lock);
822 	kobj_delete((kobj_t)m, M_MIXER);
823 
824 	d->mixer_dev = NULL;
825 
826 	return 0;
827 }
828 
829 int
830 mixer_reinit(device_t dev)
831 {
832 	struct snd_mixer *m;
833 	struct cdev *pdev;
834 	int i;
835 
836 	pdev = mixer_get_devt(dev);
837 	m = pdev->si_drv1;
838 	snd_mtxlock(m->lock);
839 
840 	i = MIXER_REINIT(m);
841 	if (i) {
842 		snd_mtxunlock(m->lock);
843 		return i;
844 	}
845 
846 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
847 		if (m->mutedevs & (1 << i))
848 			mixer_set(m, i, 0, 0);
849 		else
850 			mixer_set(m, i, 0, m->level[i]);
851 	}
852 
853 	mixer_setrecsrc(m, m->recsrc);
854 	snd_mtxunlock(m->lock);
855 
856 	return 0;
857 }
858 
859 static int
860 sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
861 {
862 	char devname[32];
863 	int error, dev;
864 	struct snd_mixer *m;
865 
866 	m = oidp->oid_arg1;
867 	snd_mtxlock(m->lock);
868 	strlcpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
869 	snd_mtxunlock(m->lock);
870 	error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
871 	snd_mtxlock(m->lock);
872 	if (error == 0 && req->newptr != NULL) {
873 		dev = mixer_lookup(devname);
874 		if (dev == -1) {
875 			snd_mtxunlock(m->lock);
876 			return EINVAL;
877 		} else {
878 			m->hwvol_mixer = dev;
879 		}
880 	}
881 	snd_mtxunlock(m->lock);
882 	return error;
883 }
884 
885 int
886 mixer_hwvol_init(device_t dev)
887 {
888 	struct snd_mixer *m;
889 	struct cdev *pdev;
890 
891 	pdev = mixer_get_devt(dev);
892 	m = pdev->si_drv1;
893 
894 	m->hwvol_mixer = SOUND_MIXER_VOLUME;
895 	m->hwvol_step = 5;
896 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
897 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
898             OID_AUTO, "hwvol_step", CTLFLAG_RWTUN, &m->hwvol_step, 0, "");
899 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
900 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
901 	    "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
902 	    m, 0, sysctl_hw_snd_hwvol_mixer, "A", "");
903 	return 0;
904 }
905 
906 void
907 mixer_hwvol_mute_locked(struct snd_mixer *m)
908 {
909 	mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer));
910 }
911 
912 void
913 mixer_hwvol_mute(device_t dev)
914 {
915 	struct snd_mixer *m;
916 	struct cdev *pdev;
917 
918 	pdev = mixer_get_devt(dev);
919 	m = pdev->si_drv1;
920 	snd_mtxlock(m->lock);
921 	mixer_hwvol_mute_locked(m);
922 	snd_mtxunlock(m->lock);
923 }
924 
925 void
926 mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
927 {
928 	int level, left, right;
929 
930 	level = mixer_get(m, m->hwvol_mixer);
931 
932 	if (level != -1) {
933 		left = level & 0xff;
934 		right = (level >> 8) & 0xff;
935 		left += left_step * m->hwvol_step;
936 		if (left < 0)
937 			left = 0;
938 		else if (left > 100)
939 			left = 100;
940 		right += right_step * m->hwvol_step;
941 		if (right < 0)
942 			right = 0;
943 		else if (right > 100)
944 			right = 100;
945 
946 		mixer_set(m, m->hwvol_mixer, m->mutedevs, left | right << 8);
947 	}
948 }
949 
950 void
951 mixer_hwvol_step(device_t dev, int left_step, int right_step)
952 {
953 	struct snd_mixer *m;
954 	struct cdev *pdev;
955 
956 	pdev = mixer_get_devt(dev);
957 	m = pdev->si_drv1;
958 	snd_mtxlock(m->lock);
959 	mixer_hwvol_step_locked(m, left_step, right_step);
960 	snd_mtxunlock(m->lock);
961 }
962 
963 int
964 mixer_busy(struct snd_mixer *m)
965 {
966 	KASSERT(m != NULL, ("NULL snd_mixer"));
967 
968 	return (m->busy);
969 }
970 
971 int
972 mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
973 {
974 	int ret;
975 
976 	KASSERT(m != NULL, ("NULL snd_mixer"));
977 
978 	snd_mtxlock(m->lock);
979 	ret = mixer_set(m, dev, m->mutedevs, left | (right << 8));
980 	snd_mtxunlock(m->lock);
981 
982 	return ((ret != 0) ? ENXIO : 0);
983 }
984 
985 int
986 mix_get(struct snd_mixer *m, u_int dev)
987 {
988 	int ret;
989 
990 	KASSERT(m != NULL, ("NULL snd_mixer"));
991 
992 	snd_mtxlock(m->lock);
993 	ret = mixer_get(m, dev);
994 	snd_mtxunlock(m->lock);
995 
996 	return (ret);
997 }
998 
999 int
1000 mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1001 {
1002 	int ret;
1003 
1004 	KASSERT(m != NULL, ("NULL snd_mixer"));
1005 
1006 	snd_mtxlock(m->lock);
1007 	ret = mixer_setrecsrc(m, src);
1008 	snd_mtxunlock(m->lock);
1009 
1010 	return ((ret != 0) ? ENXIO : 0);
1011 }
1012 
1013 u_int32_t
1014 mix_getrecsrc(struct snd_mixer *m)
1015 {
1016 	u_int32_t ret;
1017 
1018 	KASSERT(m != NULL, ("NULL snd_mixer"));
1019 
1020 	snd_mtxlock(m->lock);
1021 	ret = mixer_getrecsrc(m);
1022 	snd_mtxunlock(m->lock);
1023 
1024 	return (ret);
1025 }
1026 
1027 int
1028 mix_get_type(struct snd_mixer *m)
1029 {
1030 	KASSERT(m != NULL, ("NULL snd_mixer"));
1031 
1032 	return (m->type);
1033 }
1034 
1035 device_t
1036 mix_get_dev(struct snd_mixer *m)
1037 {
1038 	KASSERT(m != NULL, ("NULL snd_mixer"));
1039 
1040 	return (m->dev);
1041 }
1042 
1043 /* ----------------------------------------------------------------------- */
1044 
1045 static int
1046 mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
1047 {
1048 	struct snddev_info *d;
1049 	struct snd_mixer *m;
1050 
1051 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1052 		return (EBADF);
1053 
1054 	m = i_dev->si_drv1;
1055 	d = device_get_softc(m->dev);
1056 	if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
1057 		return (EBADF);
1058 
1059 	/* XXX Need Giant magic entry ??? */
1060 
1061 	snd_mtxlock(m->lock);
1062 	m->busy = 1;
1063 	snd_mtxunlock(m->lock);
1064 
1065 	return (0);
1066 }
1067 
1068 static int
1069 mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
1070 {
1071 	struct snddev_info *d;
1072 	struct snd_mixer *m;
1073 	int ret;
1074 
1075 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1076 		return (EBADF);
1077 
1078 	m = i_dev->si_drv1;
1079 	d = device_get_softc(m->dev);
1080 	if (!PCM_REGISTERED(d))
1081 		return (EBADF);
1082 
1083 	/* XXX Need Giant magic entry ??? */
1084 
1085 	snd_mtxlock(m->lock);
1086 	ret = (m->busy == 0) ? EBADF : 0;
1087 	m->busy = 0;
1088 	snd_mtxunlock(m->lock);
1089 
1090 	return (ret);
1091 }
1092 
1093 static int
1094 mixer_ioctl_channel(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1095     struct thread *td, int from)
1096 {
1097 	struct snddev_info *d;
1098 	struct snd_mixer *m;
1099 	struct pcm_channel *c, *rdch, *wrch;
1100 	pid_t pid;
1101 	int j, ret;
1102 
1103 	if (td == NULL || td->td_proc == NULL)
1104 		return (-1);
1105 
1106 	m = dev->si_drv1;
1107 	d = device_get_softc(m->dev);
1108 	j = cmd & 0xff;
1109 
1110 	switch (j) {
1111 	case SOUND_MIXER_PCM:
1112 	case SOUND_MIXER_RECLEV:
1113 	case SOUND_MIXER_DEVMASK:
1114 	case SOUND_MIXER_CAPS:
1115 	case SOUND_MIXER_STEREODEVS:
1116 		break;
1117 	default:
1118 		return (-1);
1119 		break;
1120 	}
1121 
1122 	pid = td->td_proc->p_pid;
1123 	rdch = NULL;
1124 	wrch = NULL;
1125 	c = NULL;
1126 	ret = -1;
1127 
1128 	/*
1129 	 * This is unfair. Imagine single proc opening multiple
1130 	 * instances of same direction. What we do right now
1131 	 * is looking for the first matching proc/pid, and just
1132 	 * that. Nothing more. Consider it done.
1133 	 *
1134 	 * The better approach of controlling specific channel
1135 	 * pcm or rec volume is by doing mixer ioctl
1136 	 * (SNDCTL_DSP_[SET|GET][PLAY|REC]VOL / SOUND_MIXER_[PCM|RECLEV]
1137 	 * on its open fd, rather than cracky mixer bypassing here.
1138 	 */
1139 	CHN_FOREACH(c, d, channels.pcm.opened) {
1140 		CHN_LOCK(c);
1141 		if (c->pid != pid ||
1142 		    !(c->feederflags & (1 << FEEDER_VOLUME))) {
1143 			CHN_UNLOCK(c);
1144 			continue;
1145 		}
1146 		if (rdch == NULL && c->direction == PCMDIR_REC) {
1147 			rdch = c;
1148 			if (j == SOUND_MIXER_RECLEV)
1149 				goto mixer_ioctl_channel_proc;
1150 		} else if (wrch == NULL && c->direction == PCMDIR_PLAY) {
1151 			wrch = c;
1152 			if (j == SOUND_MIXER_PCM)
1153 				goto mixer_ioctl_channel_proc;
1154 		}
1155 		CHN_UNLOCK(c);
1156 		if (rdch != NULL && wrch != NULL)
1157 			break;
1158 	}
1159 
1160 	if (rdch == NULL && wrch == NULL)
1161 		return (-1);
1162 
1163 	if ((j == SOUND_MIXER_DEVMASK || j == SOUND_MIXER_CAPS ||
1164 	    j == SOUND_MIXER_STEREODEVS) &&
1165 	    (cmd & ~0xff) == MIXER_READ(0)) {
1166 		snd_mtxlock(m->lock);
1167 		*(int *)arg = mix_getdevs(m);
1168 		snd_mtxunlock(m->lock);
1169 		if (rdch != NULL)
1170 			*(int *)arg |= SOUND_MASK_RECLEV;
1171 		if (wrch != NULL)
1172 			*(int *)arg |= SOUND_MASK_PCM;
1173 		ret = 0;
1174 	}
1175 
1176 	return (ret);
1177 
1178 mixer_ioctl_channel_proc:
1179 
1180 	KASSERT(c != NULL, ("%s(): NULL channel", __func__));
1181 	CHN_LOCKASSERT(c);
1182 
1183 	if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1184 		int left, right, center;
1185 
1186 		left = *(int *)arg & 0x7f;
1187 		right = (*(int *)arg >> 8) & 0x7f;
1188 		center = (left + right) >> 1;
1189 		chn_setvolume_multi(c, SND_VOL_C_PCM, left, right, center);
1190 	} else if ((cmd & ~0xff) == MIXER_READ(0)) {
1191 		*(int *)arg = CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FL);
1192 		*(int *)arg |=
1193 		    CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FR) << 8;
1194 	}
1195 
1196 	CHN_UNLOCK(c);
1197 
1198 	return (0);
1199 }
1200 
1201 static int
1202 mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1203     struct thread *td)
1204 {
1205 	struct snddev_info *d;
1206 	int ret;
1207 
1208 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1209 		return (EBADF);
1210 
1211 	d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
1212 	if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
1213 		return (EBADF);
1214 
1215 	PCM_GIANT_ENTER(d);
1216 	PCM_ACQUIRE_QUICK(d);
1217 
1218 	ret = -1;
1219 
1220 	if (mixer_bypass != 0 && (d->flags & SD_F_VPC))
1221 		ret = mixer_ioctl_channel(i_dev, cmd, arg, mode, td,
1222 		    MIXER_CMD_CDEV);
1223 
1224 	if (ret == -1)
1225 		ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td,
1226 		    MIXER_CMD_CDEV);
1227 
1228 	PCM_RELEASE_QUICK(d);
1229 	PCM_GIANT_LEAVE(d);
1230 
1231 	return (ret);
1232 }
1233 
1234 static void
1235 mixer_mixerinfo(struct snd_mixer *m, mixer_info *mi)
1236 {
1237 	bzero((void *)mi, sizeof(*mi));
1238 	strlcpy(mi->id, m->name, sizeof(mi->id));
1239 	strlcpy(mi->name, device_get_desc(m->dev), sizeof(mi->name));
1240 	mi->modify_counter = m->modify_counter;
1241 }
1242 
1243 /*
1244  * XXX Make sure you can guarantee concurrency safety before calling this
1245  *     function, be it through Giant, PCM_*, etc !
1246  */
1247 int
1248 mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1249     struct thread *td, int from)
1250 {
1251 	struct snd_mixer *m;
1252 	int ret = EINVAL, *arg_i = (int *)arg;
1253 	int v = -1, j = cmd & 0xff;
1254 
1255 	/*
1256 	 * Certain ioctls may be made on any type of device (audio, mixer,
1257 	 * and MIDI).  Handle those special cases here.
1258 	 */
1259 	if (IOCGROUP(cmd) == 'X') {
1260 		switch (cmd) {
1261 		case SNDCTL_SYSINFO:
1262 			sound_oss_sysinfo((oss_sysinfo *)arg);
1263 			return (0);
1264 		case SNDCTL_CARDINFO:
1265 			return (sound_oss_card_info((oss_card_info *)arg));
1266 	    	case SNDCTL_AUDIOINFO:
1267 			return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
1268 			    false));
1269 	    	case SNDCTL_AUDIOINFO_EX:
1270 			return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
1271 			    true));
1272 		case SNDCTL_ENGINEINFO:
1273 			return (dsp_oss_engineinfo(i_dev, (oss_audioinfo *)arg));
1274 		case SNDCTL_MIXERINFO:
1275 			return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
1276 		}
1277 		return (EINVAL);
1278 	}
1279 
1280 	m = i_dev->si_drv1;
1281 
1282 	if (m == NULL)
1283 		return (EBADF);
1284 
1285 	snd_mtxlock(m->lock);
1286 	if (from == MIXER_CMD_CDEV && !m->busy) {
1287 		snd_mtxunlock(m->lock);
1288 		return (EBADF);
1289 	}
1290 	switch (cmd) {
1291 	case SNDCTL_DSP_GET_RECSRC_NAMES:
1292 		bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo));
1293 		ret = 0;
1294 		goto done;
1295 	case SNDCTL_DSP_GET_RECSRC:
1296 		ret = mixer_get_recroute(m, arg_i);
1297 		goto done;
1298 	case SNDCTL_DSP_SET_RECSRC:
1299 		ret = mixer_set_recroute(m, *arg_i);
1300 		goto done;
1301 	case OSS_GETVERSION:
1302 		*arg_i = SOUND_VERSION;
1303 		ret = 0;
1304 		goto done;
1305 	case SOUND_MIXER_INFO:
1306 		mixer_mixerinfo(m, (mixer_info *)arg);
1307 		ret = 0;
1308 		goto done;
1309 	}
1310 	if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1311 		switch (j) {
1312 		case SOUND_MIXER_RECSRC:
1313 			ret = mixer_setrecsrc(m, *arg_i);
1314 			break;
1315 		case SOUND_MIXER_MUTE:
1316 			mix_setmutedevs(m, *arg_i);
1317 			ret = 0;
1318 			break;
1319 		default:
1320 			ret = mixer_set(m, j, m->mutedevs, *arg_i);
1321 			break;
1322 		}
1323 		snd_mtxunlock(m->lock);
1324 		return ((ret == 0) ? 0 : ENXIO);
1325 	}
1326 	if ((cmd & ~0xff) == MIXER_READ(0)) {
1327 		switch (j) {
1328 		case SOUND_MIXER_DEVMASK:
1329 		case SOUND_MIXER_CAPS:
1330 		case SOUND_MIXER_STEREODEVS:
1331 			v = mix_getdevs(m);
1332 			break;
1333 		case SOUND_MIXER_MUTE:
1334 			v = mix_getmutedevs(m);
1335 			break;
1336 		case SOUND_MIXER_RECMASK:
1337 			v = mix_getrecdevs(m);
1338 			break;
1339 		case SOUND_MIXER_RECSRC:
1340 			v = mixer_getrecsrc(m);
1341 			break;
1342 		default:
1343 			v = mixer_get(m, j);
1344 			break;
1345 		}
1346 		*arg_i = v;
1347 		snd_mtxunlock(m->lock);
1348 		return ((v != -1) ? 0 : ENXIO);
1349 	}
1350 done:
1351 	snd_mtxunlock(m->lock);
1352 	return (ret);
1353 }
1354 
1355 static void
1356 mixer_clone(void *arg,
1357     struct ucred *cred,
1358     char *name, int namelen, struct cdev **dev)
1359 {
1360 	struct snddev_info *d;
1361 
1362 	if (*dev != NULL)
1363 		return;
1364 	if (strcmp(name, "mixer") == 0) {
1365 		bus_topo_lock();
1366 		d = devclass_get_softc(pcm_devclass, snd_unit);
1367 		/* See related comment in dsp_clone(). */
1368 		if (d != NULL && PCM_REGISTERED(d) && d->mixer_dev != NULL) {
1369 			*dev = d->mixer_dev;
1370 			dev_ref(*dev);
1371 		}
1372 		bus_topo_unlock();
1373 	}
1374 }
1375 
1376 static void
1377 mixer_sysinit(void *p)
1378 {
1379 	if (mixer_ehtag != NULL)
1380 		return;
1381 	mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000);
1382 }
1383 
1384 static void
1385 mixer_sysuninit(void *p)
1386 {
1387 	if (mixer_ehtag == NULL)
1388 		return;
1389 	EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag);
1390 	mixer_ehtag = NULL;
1391 }
1392 
1393 SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL);
1394 SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL);
1395 
1396 static void
1397 mixer_oss_mixerinfo_unavail(oss_mixerinfo *mi, int unit)
1398 {
1399 	bzero(mi, sizeof(*mi));
1400 	mi->dev = unit;
1401 	snprintf(mi->id, sizeof(mi->id), "mixer%d (n/a)", unit);
1402 	snprintf(mi->name, sizeof(mi->name), "pcm%d:mixer (unavailable)", unit);
1403 	mi->card_number = unit;
1404 	mi->legacy_device = unit;
1405 }
1406 
1407 /**
1408  * @brief Handler for SNDCTL_MIXERINFO
1409  *
1410  * This function searches for a mixer based on the numeric ID stored
1411  * in oss_miserinfo::dev.  If set to -1, then information about the
1412  * current mixer handling the request is provided.  Note, however, that
1413  * this ioctl may be made with any sound device (audio, mixer, midi).
1414  *
1415  * @note Caller must not hold any PCM device, channel, or mixer locks.
1416  *
1417  * See http://manuals.opensound.com/developer/SNDCTL_MIXERINFO.html for
1418  * more information.
1419  *
1420  * @param i_dev	character device on which the ioctl arrived
1421  * @param arg	user argument (oss_mixerinfo *)
1422  *
1423  * @retval EINVAL	oss_mixerinfo::dev specified a bad value
1424  * @retval 0		success
1425  */
1426 int
1427 mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
1428 {
1429 	struct snddev_info *d;
1430 	struct snd_mixer *m;
1431 	int i;
1432 
1433 	/*
1434 	 * If probing the device handling the ioctl, make sure it's a mixer
1435 	 * device.  (This ioctl is valid on audio, mixer, and midi devices.)
1436 	 */
1437 	if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw)
1438 		return (EINVAL);
1439 
1440 	d = NULL;
1441 	m = NULL;
1442 
1443 	/*
1444 	 * There's a 1:1 relationship between mixers and PCM devices, so
1445 	 * begin by iterating over PCM devices and search for our mixer.
1446 	 */
1447 	for (i = 0; pcm_devclass != NULL &&
1448 	    i < devclass_get_maxunit(pcm_devclass); i++) {
1449 		d = devclass_get_softc(pcm_devclass, i);
1450 		if (!PCM_REGISTERED(d) || PCM_DETACHING(d)) {
1451 			if ((mi->dev == -1 && i == snd_unit) || mi->dev == i) {
1452 				mixer_oss_mixerinfo_unavail(mi, i);
1453 				return (0);
1454 			} else
1455 				continue;
1456 		}
1457 
1458 		/* XXX Need Giant magic entry */
1459 
1460 		/* See the note in function docblock. */
1461 		PCM_UNLOCKASSERT(d);
1462 		PCM_LOCK(d);
1463 
1464 		if (!((d->mixer_dev == i_dev && mi->dev == -1) ||
1465 		    mi->dev == i)) {
1466 			PCM_UNLOCK(d);
1467 			continue;
1468 		}
1469 
1470 		if (d->mixer_dev->si_drv1 == NULL) {
1471 			mixer_oss_mixerinfo_unavail(mi, i);
1472 			PCM_UNLOCK(d);
1473 			return (0);
1474 		}
1475 
1476 		m = d->mixer_dev->si_drv1;
1477 		mtx_lock(m->lock);
1478 
1479 		/*
1480 		 * At this point, the following synchronization stuff
1481 		 * has happened:
1482 		 * - a specific PCM device is locked.
1483 		 * - a specific mixer device has been locked, so be
1484 		 *   sure to unlock when existing.
1485 		 */
1486 		bzero((void *)mi, sizeof(*mi));
1487 		mi->dev = i;
1488 		snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
1489 		strlcpy(mi->name, m->name, sizeof(mi->name));
1490 		mi->modify_counter = m->modify_counter;
1491 		mi->card_number = i;
1492 		/*
1493 		 * Currently, FreeBSD assumes 1:1 relationship between
1494 		 * a pcm and mixer devices, so this is hardcoded to 0.
1495 		 */
1496 		mi->port_number = 0;
1497 
1498 		/**
1499 		 * @todo Fill in @sa oss_mixerinfo::mixerhandle.
1500 		 * @note From 4Front:  "mixerhandle is an arbitrary
1501 		 *       string that identifies the mixer better than
1502 		 *       the device number (mixerinfo.dev).  Device
1503 		 *       numbers may change depending on the order the
1504 		 *       drivers are loaded. However the handle should
1505 		 *       remain the same provided that the sound card
1506 		 *       is not moved to another PCI slot."
1507 		 */
1508 
1509 		/**
1510 		 * @note
1511 		 * @sa oss_mixerinfo::magic is a reserved field.
1512 		 *
1513 		 * @par
1514 		 * From 4Front:  "magic is usually 0. However some
1515 		 * devices may have dedicated setup utilities and the
1516 		 * magic field may contain an unique driver specific
1517 		 * value (managed by [4Front])."
1518 		 */
1519 
1520 		mi->enabled = device_is_attached(m->dev) ? 1 : 0;
1521 		/**
1522 		 * The only flag for @sa oss_mixerinfo::caps is
1523 		 * currently MIXER_CAP_VIRTUAL, which I'm not sure we
1524 		 * really worry about.
1525 		 */
1526 		/**
1527 		 * Mixer extensions currently aren't supported, so
1528 		 * leave @sa oss_mixerinfo::nrext blank for now.
1529 		 */
1530 
1531 		/**
1532 		 * @todo Fill in @sa oss_mixerinfo::priority (requires
1533 		 *       touching drivers?)
1534 		 * @note The priority field is for mixer applets to
1535 		 * determine which mixer should be the default, with 0
1536 		 * being least preferred and 10 being most preferred.
1537 		 * From 4Front:  "OSS drivers like ICH use higher
1538 		 * values (10) because such chips are known to be used
1539 		 * only on motherboards.  Drivers for high end pro
1540 		 * devices use 0 because they will never be the
1541 		 * default mixer. Other devices use values 1 to 9
1542 		 * depending on the estimated probability of being the
1543 		 * default device.
1544 		 */
1545 
1546 		snprintf(mi->devnode, sizeof(mi->devnode), "/dev/mixer%d", i);
1547 		mi->legacy_device = i;
1548 
1549 		mtx_unlock(m->lock);
1550 
1551 		PCM_UNLOCK(d);
1552 
1553 		return (0);
1554 	}
1555 
1556 	return (EINVAL);
1557 }
1558 
1559 /*
1560  * Allow the sound driver to use the mixer lock to protect its mixer
1561  * data:
1562  */
1563 struct mtx *
1564 mixer_get_lock(struct snd_mixer *m)
1565 {
1566 	if (m->lock == NULL) {
1567 		return (&Giant);
1568 	}
1569 	return (m->lock);
1570 }
1571 
1572 int
1573 mix_get_locked(struct snd_mixer *m, u_int dev, int *pleft, int *pright)
1574 {
1575 	int level;
1576 
1577 	level = mixer_get(m, dev);
1578 	if (level < 0) {
1579 		*pright = *pleft = -1;
1580 		return (-1);
1581 	}
1582 
1583 	*pleft = level & 0xFF;
1584 	*pright = (level >> 8) & 0xFF;
1585 
1586 	return (0);
1587 }
1588 
1589 int
1590 mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right)
1591 {
1592 	int level;
1593 
1594 	level = (left & 0xFF) | ((right & 0xFF) << 8);
1595 
1596 	return (mixer_set(m, dev, m->mutedevs, level));
1597 }
1598